21
21
22
22
#include " pointer_offset_size.h"
23
23
24
+ member_offset_iterator::member_offset_iterator (const struct_typet& _type,
25
+ const namespacet& _ns) :
26
+ current({0 ,0 }),
27
+ type(_type),
28
+ ns(_ns),
29
+ bit_field_bits(0 )
30
+ {
31
+ }
32
+
33
+ member_offset_iterator& member_offset_iterator::operator ++()
34
+ {
35
+ if (current.second !=-1 ) // Already failed?
36
+ {
37
+ const auto & comp=type.components ()[current.first ];
38
+ if (comp.type ().id ()==ID_c_bit_field)
39
+ {
40
+ // take the extra bytes needed
41
+ std::size_t w=to_c_bit_field_type (comp.type ()).get_width ();
42
+ for (; w>bit_field_bits; ++current.second , bit_field_bits+=8 );
43
+ bit_field_bits-=w;
44
+ }
45
+ else
46
+ {
47
+ const typet &subtype=comp.type ();
48
+ mp_integer sub_size=pointer_offset_size (subtype, ns);
49
+ if (sub_size==-1 ) current.second =-1 ; // give up
50
+ else current.second +=sub_size;
51
+ }
52
+ }
53
+ ++current.first ;
54
+ return *this ;
55
+ }
56
+
24
57
/* ******************************************************************\
25
58
26
59
Function: member_offset
@@ -39,35 +72,18 @@ mp_integer member_offset(
39
72
const namespacet &ns)
40
73
{
41
74
const struct_typet::componentst &components=type.components ();
42
-
43
- mp_integer result=0 ;
44
- std::size_t bit_field_bits=0 ;
75
+ member_offset_iterator offsets (type,ns);
45
76
46
77
for (struct_typet::componentst::const_iterator
47
78
it=components.begin ();
48
- it!=components.end ();
49
- it++ )
79
+ it!=components.end () && offsets-> second !=- 1 ;
80
+ ++it, ++offsets )
50
81
{
51
82
if (it->get_name ()==member)
52
83
break ;
53
-
54
- if (it->type ().id ()==ID_c_bit_field)
55
- {
56
- // take the extra bytes needed
57
- std::size_t w=to_c_bit_field_type (it->type ()).get_width ();
58
- for (; w>bit_field_bits; ++result, bit_field_bits+=8 );
59
- bit_field_bits-=w;
60
- }
61
- else
62
- {
63
- const typet &subtype=it->type ();
64
- mp_integer sub_size=pointer_offset_size (subtype, ns);
65
- if (sub_size==-1 ) return -1 ; // give up
66
- result+=sub_size;
67
- }
68
84
}
69
85
70
- return result ;
86
+ return offsets-> second ;
71
87
}
72
88
73
89
/* ******************************************************************\
@@ -616,3 +632,67 @@ exprt build_sizeof_expr(
616
632
617
633
return result;
618
634
}
635
+
636
+ bool get_subexpression_at_offset (
637
+ exprt& result,
638
+ mp_integer offset,
639
+ const typet& target_type_raw,
640
+ const namespacet& ns)
641
+ {
642
+ const typet& source_type=ns.follow (result.type ());
643
+ const typet& target_type=ns.follow (target_type_raw);
644
+
645
+ if (offset==0 && source_type==target_type)
646
+ return true ;
647
+
648
+ if (source_type.id ()==ID_struct)
649
+ {
650
+ const auto & st=to_struct_type (source_type);
651
+ const struct_typet::componentst &components=st.components ();
652
+ member_offset_iterator offsets (st,ns);
653
+ while (offsets->first <components.size () && offsets->second !=-1 && offsets->second <=offset)
654
+ {
655
+ auto nextit=offsets;
656
+ ++nextit;
657
+ if ((offsets->first +1 )==components.size () || offset<nextit->second )
658
+ {
659
+ // This field might be, or might contain, the answer.
660
+ result=member_exprt (result,
661
+ components[offsets->first ].get_name (),
662
+ components[offsets->first ].type ());
663
+ return get_subexpression_at_offset (result, offset - offsets->second , target_type, ns);
664
+ }
665
+ ++offsets;
666
+ }
667
+ return false ;
668
+ }
669
+ else if (source_type.id ()==ID_array)
670
+ {
671
+ // A cell of the array might be, or contain, the subexpression we're looking for.
672
+ const auto & at=to_array_type (source_type);
673
+ mp_integer elem_size=pointer_offset_size (at.subtype (),ns);
674
+ if (elem_size==-1 )
675
+ return false ;
676
+ mp_integer cellidx=offset / elem_size;
677
+ if (cellidx < 0 || !cellidx.is_long ())
678
+ return false ;
679
+ offset=offset % elem_size;
680
+ result=index_exprt (result,from_integer (cellidx,unsignedbv_typet (64 )));
681
+ return get_subexpression_at_offset (result,offset,target_type,ns);
682
+ }
683
+ else
684
+ return false ;
685
+
686
+ }
687
+
688
+ bool get_subexpression_at_offset (
689
+ exprt& result,
690
+ const exprt& offset,
691
+ const typet& target_type,
692
+ const namespacet& ns)
693
+ {
694
+ mp_integer offset_const;
695
+ if (to_integer (offset,offset_const))
696
+ return false ;
697
+ return get_subexpression_at_offset (result,offset_const,target_type,ns);
698
+ }
0 commit comments