Skip to content

Commit 0a3f3ad

Browse files
committed
Add helper functions to find members or array indices with given offsets in a complex type.
1 parent 569b4fc commit 0a3f3ad

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/util/pointer_offset_size.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,3 +632,66 @@ exprt build_sizeof_expr(
632632

633633
return result;
634634
}
635+
636+
bool get_subexpression_at_offset(
637+
exprt& result,
638+
mp_integer offset,
639+
const typet& target_type,
640+
const namespacet& ns)
641+
{
642+
if(offset==0 && result.type()==target_type)
643+
return true;
644+
645+
const typet& source_type=result.type();
646+
647+
if(source_type.id()==ID_struct)
648+
{
649+
const auto& st=to_struct_type(source_type);
650+
const struct_typet::componentst &components=st.components();
651+
member_offset_iterator offsets(st,ns);
652+
while(offsets->first<components.size() && offsets->second!=-1 && offsets->second<=offset)
653+
{
654+
auto nextit=offsets;
655+
++nextit;
656+
if((offsets->first+1)==components.size() || offset<nextit->second)
657+
{
658+
// This field might be, or might contain, the answer.
659+
result=member_exprt(result,
660+
components[offsets->first].get_name(),
661+
components[offsets->first].type());
662+
return get_subexpression_at_offset(result, offset - offsets->second, target_type, ns);
663+
}
664+
++offsets;
665+
}
666+
return false;
667+
}
668+
else if(source_type.id()==ID_array)
669+
{
670+
// A cell of the array might be, or contain, the subexpression we're looking for.
671+
const auto& at=to_array_type(source_type);
672+
mp_integer elem_size=pointer_offset_size(at.subtype(),ns);
673+
if(elem_size==-1)
674+
return false;
675+
mp_integer cellidx=offset / elem_size;
676+
if(cellidx < 0 || !cellidx.is_long())
677+
return false;
678+
offset=offset % elem_size;
679+
result=index_exprt(result,from_integer(cellidx,unsignedbv_typet(64)));
680+
return get_subexpression_at_offset(result,offset,target_type,ns);
681+
}
682+
else
683+
return false;
684+
685+
}
686+
687+
bool get_subexpression_at_offset(
688+
exprt& result,
689+
const exprt& offset,
690+
const typet& target_type,
691+
const namespacet& ns)
692+
{
693+
mp_integer offset_const;
694+
if(to_integer(offset,offset_const))
695+
return false;
696+
return get_subexpression_at_offset(result,offset_const,target_type,ns);
697+
}

src/util/pointer_offset_size.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,16 @@ exprt build_sizeof_expr(
7171
const constant_exprt &expr,
7272
const namespacet &ns);
7373

74+
bool get_subexpression_at_offset(
75+
exprt& result,
76+
mp_integer offset,
77+
const typet& target_type,
78+
const namespacet& ns);
79+
80+
bool get_subexpression_at_offset(
81+
exprt& result,
82+
const exprt& offset,
83+
const typet& target_type,
84+
const namespacet& ns);
85+
7486
#endif

0 commit comments

Comments
 (0)