Skip to content

Commit 52d4326

Browse files
Merge pull request diffblue#731 from tautschnig/more-rewriting
Simplifier and symex rewriting fixes/extensions
2 parents 2db8c45 + 14c00dc commit 52d4326

File tree

4 files changed

+128
-73
lines changed

4 files changed

+128
-73
lines changed

src/goto-symex/symex_clean_expr.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,13 @@ void goto_symext::process_array_expr_rec(
6767
expr.swap(tmp);
6868
}
6969
else
70+
{
7071
Forall_operands(it, expr)
7172
{
7273
typet t=it->type();
7374
process_array_expr_rec(*it, t);
7475
}
76+
}
7577

7678
if(!base_type_eq(expr.type(), type, ns))
7779
{
@@ -166,12 +168,41 @@ void goto_symext::replace_array_equal(exprt &expr)
166168
replace_array_equal(*it);
167169
}
168170

171+
/// Rewrite index/member expressions in byte_extract to offset
172+
static void adjust_byte_extract_rec(exprt &expr, const namespacet &ns)
173+
{
174+
Forall_operands(it, expr)
175+
adjust_byte_extract_rec(*it, ns);
176+
177+
if(expr.id()==ID_byte_extract_big_endian ||
178+
expr.id()==ID_byte_extract_little_endian)
179+
{
180+
byte_extract_exprt &be=to_byte_extract_expr(expr);
181+
if(be.op().id()==ID_symbol &&
182+
to_ssa_expr(be.op()).get_original_expr().get_bool(ID_C_invalid_object))
183+
return;
184+
185+
object_descriptor_exprt ode;
186+
ode.build(expr, ns);
187+
188+
be.op()=ode.root_object();
189+
be.offset()=ode.offset();
190+
}
191+
}
192+
169193
void goto_symext::clean_expr(
170194
exprt &expr,
171195
statet &state,
172196
const bool write)
173197
{
174198
replace_nondet(expr);
175199
dereference(expr, state, write);
200+
201+
// make sure all remaining byte extract operations use the root
202+
// object to avoid nesting of with/update and byte_update when on
203+
// lhs
204+
if(write)
205+
adjust_byte_extract_rec(expr, ns);
206+
176207
replace_array_equal(expr);
177208
}

src/solvers/flattening/flatten_byte_operators.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,12 @@ exprt flatten_byte_extract(
242242

243243
byte_extract_exprt tmp(unpacked);
244244
tmp.type()=subtype;
245-
tmp.offset()=simplify_expr(new_offset, ns);
245+
tmp.offset()=new_offset;
246246

247247
array.copy_to_operands(flatten_byte_extract(tmp, ns));
248248
}
249249

250-
return array;
250+
return simplify_expr(array, ns);
251251
}
252252
}
253253
else if(type.id()==ID_struct)
@@ -277,13 +277,13 @@ exprt flatten_byte_extract(
277277

278278
byte_extract_exprt tmp(unpacked);
279279
tmp.type()=comp.type();
280-
tmp.offset()=simplify_expr(new_offset, ns);
280+
tmp.offset()=new_offset;
281281

282282
s.move_to_operands(tmp);
283283
}
284284

285285
if(!failed)
286-
return s;
286+
return simplify_expr(s, ns);
287287
}
288288

289289
const exprt &root=unpacked.op();
@@ -333,7 +333,7 @@ exprt flatten_byte_extract(
333333
{
334334
concatenation_exprt concatenation(src.type());
335335
concatenation.operands().swap(op);
336-
return concatenation;
336+
return simplify_expr(concatenation, ns);
337337
}
338338
}
339339

@@ -413,7 +413,7 @@ exprt flatten_byte_update(
413413
result.swap(with_expr);
414414
}
415415

416-
return result;
416+
return simplify_expr(result, ns);
417417
}
418418
else // sub_size!=1
419419
{
@@ -512,7 +512,7 @@ exprt flatten_byte_update(
512512
result=with_expr;
513513
}
514514

515-
return result;
515+
return simplify_expr(result, ns);
516516
}
517517
}
518518
else
@@ -583,7 +583,7 @@ exprt flatten_byte_update(
583583
// original_bits |= newvalue
584584
bitor_exprt bitor_expr(bitand_expr, value_shifted);
585585

586-
return bitor_expr;
586+
return simplify_expr(bitor_expr, ns);
587587
}
588588
else
589589
{

src/util/simplify_expr.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,14 @@ bool simplify_exprt::simplify_typecast(exprt &expr)
318318
// (int)((T*)0 + int) -> (int)(sizeof(T)*(size_t)int) if NULL is zero
319319
if(config.ansi_c.NULL_is_zero &&
320320
(expr_type.id()==ID_signedbv || expr_type.id()==ID_unsignedbv) &&
321+
op_type.id()==ID_pointer &&
321322
expr.op0().id()==ID_plus &&
322323
expr.op0().operands().size()==2 &&
323-
expr.op0().op0().id()==ID_typecast &&
324+
((expr.op0().op0().id()==ID_typecast &&
324325
expr.op0().op0().operands().size()==1 &&
325-
expr.op0().op0().op0().is_zero() &&
326-
op_type.id()==ID_pointer)
326+
expr.op0().op0().op0().is_zero()) ||
327+
(expr.op0().op0().is_constant() &&
328+
to_constant_expr(expr.op0().op0()).get_value()==ID_NULL)))
327329
{
328330
mp_integer sub_size=pointer_offset_size(op_type.subtype(), ns);
329331
if(sub_size!=-1)
@@ -727,6 +729,20 @@ bool simplify_exprt::simplify_typecast(exprt &expr)
727729
return false;
728730
}
729731
}
732+
else if(operand.id()==ID_address_of)
733+
{
734+
const exprt &o=to_address_of_expr(operand).object();
735+
736+
// turn &array into &array[0] when casting to pointer-to-element-type
737+
if(o.type().id()==ID_array &&
738+
base_type_eq(expr_type, pointer_type(o.type().subtype()), ns))
739+
{
740+
expr=address_of_exprt(index_exprt(o, from_integer(0, size_type())));
741+
742+
simplify_rec(expr);
743+
return false;
744+
}
745+
}
730746

731747
return true;
732748
}
@@ -1826,6 +1842,7 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
18261842
index_exprt(
18271843
result,
18281844
from_integer(offset, expr.offset().type()));
1845+
result.make_typecast(expr.type());
18291846

18301847
if(!base_type_eq(expr.type(), op_type_ptr->subtype(), ns))
18311848
result.make_typecast(expr.type());
@@ -1886,7 +1903,7 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
18861903
simplify_member(expr.op());
18871904
expr.offset()=
18881905
from_integer(offset-m_offset_bits/8, expr.offset().type());
1889-
simplify_rec(expr.offset());
1906+
simplify_rec(expr);
18901907

18911908
return false;
18921909
}
@@ -2116,6 +2133,14 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
21162133

21172134
return false;
21182135
}
2136+
2137+
if(result_expr.is_not_nil())
2138+
{
2139+
simplify_rec(result_expr);
2140+
expr.swap(result_expr);
2141+
2142+
return false;
2143+
}
21192144
}
21202145

21212146
// replace elements of array or struct expressions, possibly using

src/util/simplify_expr_boolean.cpp

Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,60 @@ bool simplify_exprt::simplify_boolean(exprt &expr)
7272
return false;
7373
}
7474
}
75-
else if(expr.id()==ID_or ||
76-
expr.id()==ID_and ||
77-
expr.id()==ID_xor)
75+
else if(expr.id()==ID_xor)
7876
{
79-
if(operands.empty())
80-
return true;
81-
8277
bool result=true;
8378

84-
exprt::operandst::const_iterator last;
85-
bool last_set=false;
86-
8779
bool negate=false;
8880

89-
for(exprt::operandst::iterator it=operands.begin();
81+
for(exprt::operandst::const_iterator it=operands.begin();
82+
it!=operands.end();)
83+
{
84+
if(it->type().id()!=ID_bool)
85+
return true;
86+
87+
bool erase;
88+
89+
if(it->is_true())
90+
{
91+
erase=true;
92+
negate=!negate;
93+
}
94+
else
95+
erase=it->is_false();
96+
97+
if(erase)
98+
{
99+
it=operands.erase(it);
100+
result=false;
101+
}
102+
else
103+
it++;
104+
}
105+
106+
if(operands.empty())
107+
{
108+
expr.make_bool(negate);
109+
return false;
110+
}
111+
else if(operands.size()==1)
112+
{
113+
exprt tmp(operands.front());
114+
if(negate)
115+
tmp.make_not();
116+
expr.swap(tmp);
117+
return false;
118+
}
119+
120+
return result;
121+
}
122+
else if(expr.id()==ID_and || expr.id()==ID_or)
123+
{
124+
std::unordered_set<exprt, irep_hash> expr_set;
125+
126+
bool result=true;
127+
128+
for(exprt::operandst::const_iterator it=operands.begin();
90129
it!=operands.end();)
91130
{
92131
if(it->type().id()!=ID_bool)
@@ -106,77 +145,37 @@ bool simplify_exprt::simplify_boolean(exprt &expr)
106145
return false;
107146
}
108147

109-
bool erase;
110-
111-
if(expr.id()==ID_and)
112-
erase=is_true;
113-
else if(is_true && expr.id()==ID_xor)
114-
{
115-
erase=true;
116-
negate=!negate;
117-
}
118-
else
119-
erase=is_false;
120-
121-
if(last_set && *it==*last &&
122-
(expr.id()==ID_or || expr.id()==ID_and))
123-
erase=true; // erase duplicate operands
148+
bool erase=
149+
(expr.id()==ID_and ? is_true : is_false) ||
150+
!expr_set.insert(*it).second;
124151

125152
if(erase)
126153
{
127154
it=operands.erase(it);
128155
result=false;
129156
}
130157
else
131-
{
132-
last=it;
133-
last_set=true;
134158
it++;
135-
}
136159
}
137160

138161
// search for a and !a
139-
if(expr.id()==ID_and || expr.id()==ID_or)
140-
{
141-
// first gather all the a's with !a
142-
143-
std::unordered_set<exprt, irep_hash> expr_set;
144-
145-
forall_operands(it, expr)
146-
if(it->id()==ID_not &&
147-
it->operands().size()==1 &&
148-
it->type().id()==ID_bool)
149-
expr_set.insert(it->op0());
150-
151-
// now search for a
152-
153-
if(!expr_set.empty())
162+
for(const exprt &op : operands)
163+
if(op.id()==ID_not &&
164+
op.operands().size()==1 &&
165+
op.type().id()==ID_bool &&
166+
expr_set.find(op.op0())!=expr_set.end())
154167
{
155-
forall_operands(it, expr)
156-
{
157-
if(it->id()!=ID_not &&
158-
expr_set.find(*it)!=expr_set.end())
159-
{
160-
expr.make_bool(expr.id()==ID_or);
161-
return false;
162-
}
163-
}
168+
expr.make_bool(expr.id()==ID_or);
169+
return false;
164170
}
165-
}
166171

167172
if(operands.empty())
168173
{
169-
if(expr.id()==ID_and || negate)
170-
expr=true_exprt();
171-
else
172-
expr=false_exprt();
173-
174+
expr.make_bool(expr.id()==ID_and);
174175
return false;
175176
}
176177
else if(operands.size()==1)
177178
{
178-
if(negate)
179-
expr.op0().make_not();
180179
exprt tmp(operands.front());
181180
expr.swap(tmp);
182181
return false;

0 commit comments

Comments
 (0)