12
12
#include " pointer_offset_size.h"
13
13
14
14
#include " arith_tools.h"
15
+ #include " base_type.h"
16
+ #include " byte_operators.h"
15
17
#include " c_types.h"
16
18
#include " invariant.h"
17
19
#include " namespace.h"
@@ -623,58 +625,84 @@ exprt build_sizeof_expr(
623
625
624
626
exprt get_subexpression_at_offset (
625
627
const exprt &expr,
626
- mp_integer offset,
628
+ const mp_integer & offset,
627
629
const typet &target_type_raw,
630
+ const irep_idt &byte_extract_op,
628
631
const namespacet &ns)
629
632
{
630
- exprt result = expr;
631
- const typet &source_type=ns.follow (result.type ());
632
- const typet &target_type=ns.follow (target_type_raw);
633
+ if (offset == 0 && base_type_eq (expr.type (), target_type_raw, ns))
634
+ {
635
+ exprt result = expr;
636
+
637
+ if (expr.type () != target_type_raw)
638
+ result.type () = target_type_raw;
633
639
634
- if (offset==0 && source_type==target_type)
635
640
return result;
641
+ }
642
+
643
+ const typet &source_type = ns.follow (expr.type ());
644
+ const mp_integer target_size = pointer_offset_bits (target_type_raw, ns);
645
+ if (target_size < 0 )
646
+ return nil_exprt ();
636
647
637
648
if (source_type.id ()==ID_struct)
638
649
{
639
- const auto &st=to_struct_type (source_type);
640
- const struct_typet::componentst &components=st.components ();
641
- member_offset_iterator offsets (st, ns);
642
- while (offsets->first <components.size () &&
643
- offsets->second !=-1 &&
644
- offsets->second <=offset)
650
+ const struct_typet &struct_type = to_struct_type (source_type);
651
+
652
+ mp_integer m_offset_bits = 0 ;
653
+ for (const auto &component : struct_type.components ())
645
654
{
646
- auto nextit=offsets;
647
- ++nextit;
648
- if ((offsets->first +1 )==components.size () || offset<nextit->second )
655
+ mp_integer m_size = pointer_offset_bits (component.type (), ns);
656
+ if (m_size < 0 )
657
+ return nil_exprt ();
658
+
659
+ if (
660
+ offset * 8 >= m_offset_bits && m_offset_bits % 8 == 0 &&
661
+ offset * 8 + target_size <= m_offset_bits + m_size)
649
662
{
650
- // This field might be, or might contain, the answer.
651
- result=
652
- member_exprt (
653
- result,
654
- components[offsets->first ].get_name (),
655
- components[offsets->first ].type ());
656
- return
657
- get_subexpression_at_offset (
658
- result, offset-offsets->second , target_type, ns);
663
+ const member_exprt member (expr, component.get_name (), component.type ());
664
+ return get_subexpression_at_offset (
665
+ member,
666
+ offset - m_offset_bits / 8 ,
667
+ target_type_raw,
668
+ byte_extract_op,
669
+ ns);
659
670
}
660
- ++offsets;
671
+
672
+ m_offset_bits += m_size;
661
673
}
662
- return nil_exprt ();
663
674
}
664
675
else if (source_type.id ()==ID_array)
665
676
{
666
- // A cell of the array might be, or contain, the subexpression
667
- // we're looking for.
668
- const auto &at=to_array_type (source_type);
669
- mp_integer elem_size=pointer_offset_size (at.subtype (), ns);
670
- if (elem_size==-1 )
671
- return nil_exprt ();
672
- mp_integer cellidx=offset/elem_size;
673
- if (cellidx < 0 || !cellidx.is_long ())
677
+ const array_typet &array_type = to_array_type (source_type);
678
+
679
+ // no arrays of non-byte, zero-, or unknown-sized objects
680
+ mp_integer sub_size = pointer_offset_bits (array_type.subtype (), ns);
681
+ if (sub_size <= 0 || sub_size % 8 != 0 )
674
682
return nil_exprt ();
675
- offset=offset%elem_size;
676
- result=index_exprt (result, from_integer (cellidx, unsignedbv_typet (64 )));
677
- return get_subexpression_at_offset (result, offset, target_type, ns);
683
+
684
+ if (target_size <= sub_size)
685
+ return get_subexpression_at_offset (
686
+ index_exprt (expr, from_integer (offset / (sub_size / 8 ), index_type ())),
687
+ offset % (sub_size / 8 ),
688
+ target_type_raw,
689
+ byte_extract_op,
690
+ ns);
691
+ }
692
+
693
+ if (
694
+ offset == 0 && pointer_offset_bits (source_type, ns) == target_size &&
695
+ source_type.id () == ID_pointer && target_type_raw.id () == ID_pointer)
696
+ {
697
+ return typecast_exprt (expr, target_type_raw);
698
+ }
699
+ else if (!byte_extract_op.empty ())
700
+ {
701
+ return byte_extract_exprt (
702
+ byte_extract_op,
703
+ expr,
704
+ from_integer (offset, index_type ()),
705
+ target_type_raw);
678
706
}
679
707
else
680
708
return nil_exprt ();
@@ -684,11 +712,13 @@ exprt get_subexpression_at_offset(
684
712
const exprt &expr,
685
713
const exprt &offset,
686
714
const typet &target_type,
715
+ const irep_idt &byte_extract_op,
687
716
const namespacet &ns)
688
717
{
689
718
mp_integer offset_const;
690
719
if (to_integer (offset, offset_const))
691
720
return nil_exprt ();
692
721
693
- return get_subexpression_at_offset (expr, offset_const, target_type, ns);
722
+ return get_subexpression_at_offset (
723
+ expr, offset_const, target_type, byte_extract_op, ns);
694
724
}
0 commit comments