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,87 @@ 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 ());
663
+ const member_exprt member (expr, component.get_name (), component.type ());
656
664
return
657
665
get_subexpression_at_offset (
658
- result, offset-offsets->second , target_type, ns);
666
+ member,
667
+ offset - m_offset_bits / 8 ,
668
+ target_type_raw,
669
+ byte_extract_op,
670
+ ns);
659
671
}
660
- ++offsets;
672
+
673
+ m_offset_bits += m_size;
661
674
}
662
- return nil_exprt ();
663
675
}
664
676
else if (source_type.id ()==ID_array)
665
677
{
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 ())
678
+ const array_typet &array_type = to_array_type (source_type);
679
+
680
+ // no arrays of non-byte, zero-, or unknown-sized objects
681
+ mp_integer sub_size = pointer_offset_bits (array_type.subtype (), ns);
682
+ if (sub_size <= 0 || sub_size % 8 != 0 )
674
683
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);
684
+
685
+ if (target_size <= sub_size)
686
+ return
687
+ get_subexpression_at_offset (
688
+ index_exprt (
689
+ expr, from_integer (offset / (sub_size / 8 ), index_type ())),
690
+ offset % (sub_size / 8 ),
691
+ target_type_raw,
692
+ byte_extract_op,
693
+ ns);
694
+ }
695
+
696
+ if (offset == 0 && pointer_offset_bits (source_type, ns) == target_size &&
697
+ source_type.id () == ID_pointer && target_type_raw.id () == ID_pointer)
698
+ {
699
+ return typecast_exprt (expr, target_type_raw);
700
+ }
701
+ else if (!byte_extract_op.empty ())
702
+ {
703
+ return
704
+ byte_extract_exprt (
705
+ byte_extract_op,
706
+ expr,
707
+ from_integer (offset, index_type ()),
708
+ target_type_raw);
678
709
}
679
710
else
680
711
return nil_exprt ();
@@ -684,11 +715,14 @@ exprt get_subexpression_at_offset(
684
715
const exprt &expr,
685
716
const exprt &offset,
686
717
const typet &target_type,
718
+ const irep_idt &byte_extract_op,
687
719
const namespacet &ns)
688
720
{
689
721
mp_integer offset_const;
690
722
if (to_integer (offset, offset_const))
691
723
return nil_exprt ();
692
724
693
- return get_subexpression_at_offset (expr, offset_const, target_type, ns);
725
+ return
726
+ get_subexpression_at_offset (
727
+ expr, offset_const, target_type, byte_extract_op, ns);
694
728
}
0 commit comments