Skip to content

Commit f4fa778

Browse files
Simplifying array access and expressions with pointer offsets
We simplify expressions containing array accesses before producing a json representation of the trace. This commit also adds comments on the functions in the cpp files Includes improvements in json_goto_trace.cpp following review of PR#922
1 parent 02b7942 commit f4fa778

File tree

1 file changed

+155
-2
lines changed

1 file changed

+155
-2
lines changed

src/goto-programs/json_goto_trace.cpp

+155-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,162 @@ Author: Daniel Kroening
1414
#include <cassert>
1515

1616
#include <util/json_expr.h>
17+
#include <util/arith_tools.h>
1718

1819
#include <langapi/language_util.h>
1920

2021
#include "json_goto_trace.h"
2122

23+
/*******************************************************************\
24+
25+
Function: remove_pointer_offsets
26+
27+
Inputs:
28+
src - an expression
29+
30+
Purpose: Replaces in src, expressions of the form pointer_offset(constant)
31+
by that constant.
32+
33+
\*******************************************************************/
34+
35+
void remove_pointer_offsets(exprt &src)
36+
{
37+
if(src.id()==ID_pointer_offset && src.op0().id()==ID_constant)
38+
src=src.op0();
39+
else
40+
for(auto &op : src.operands())
41+
remove_pointer_offsets(op);
42+
}
43+
44+
/*******************************************************************\
45+
46+
Function: remove_pointer_offsets
47+
48+
Inputs:
49+
src - an expression
50+
array_symbol - a symbol expression representing an array
51+
52+
Purpose: Replaces in src, expressions of the form
53+
pointer_offset(array_symbol) by a constant value of 0.
54+
This is meant to simplify array expressions.
55+
56+
\*******************************************************************/
57+
58+
void remove_pointer_offsets(exprt &src, const symbol_exprt &array_symbol)
59+
{
60+
if(src.id()==ID_pointer_offset &&
61+
src.op0().id()==ID_constant &&
62+
src.op0().op0().id()==ID_address_of &&
63+
src.op0().op0().op0().id()==ID_index)
64+
{
65+
const index_exprt &idx=to_index_expr(src.op0().op0().op0());
66+
const irep_idt &array_id=to_symbol_expr(idx.array()).get_identifier();
67+
if(idx.array().id()==ID_symbol &&
68+
array_id==array_symbol.get_identifier() &&
69+
to_constant_expr(idx.index()).value_is_zero_string())
70+
src=from_integer(0, src.type());
71+
}
72+
else
73+
for(auto &op : src.operands())
74+
remove_pointer_offsets(op, array_symbol);
75+
}
76+
77+
/*******************************************************************\
78+
79+
Function: simplify_index
80+
81+
Inputs:
82+
idx - an expression representing an index in an array
83+
out - a reference to an unsigned value of type size_t, which will
84+
hold the result of the simplification if it is successful
85+
86+
Outputs: Boolean flag that is true if the `idx` expression could not be
87+
simplified into a unsigned constant value.
88+
89+
Purpose: Simplify the expression in index as much as possible to try
90+
to get an unsigned constant.
91+
92+
\*******************************************************************/
93+
94+
bool simplify_index(const exprt &idx, std::size_t &out)
95+
{
96+
if(idx.id()==ID_constant)
97+
{
98+
std::string value_str(id2string(to_constant_expr(idx).get_value()));
99+
mp_integer int_value=binary2integer(value_str, false);
100+
if(int_value>std::numeric_limits<std::size_t>::max())
101+
return true;
102+
out=int_value.to_long();
103+
return false;
104+
}
105+
else if(idx.id()==ID_plus)
106+
{
107+
std::size_t l, r;
108+
if(!simplify_index(idx.op0(), l) && !simplify_index(idx.op1(), r))
109+
{
110+
out=l+r;
111+
return false;
112+
}
113+
}
114+
115+
return true;
116+
}
117+
118+
/*******************************************************************\
119+
120+
Function: simplify_array_access
121+
122+
Inputs:
123+
src - an expression potentialy containing array accesses (index_expr)
124+
125+
Outputs: an expression similar in meaning to src but where array accesses
126+
have been simplified
127+
128+
Purpose: Simplify an expression before putting it in the json format
129+
130+
\*******************************************************************/
131+
132+
exprt simplify_array_access(const exprt &src)
133+
{
134+
if(src.id()==ID_index && to_index_expr(src).array().id()==ID_symbol)
135+
{
136+
// Case where the array is a symbol.
137+
const symbol_exprt &array_symbol=to_symbol_expr(to_index_expr(src).array());
138+
exprt simplified_index=to_index_expr(src).index();
139+
// We remove potential appearances of `pointer_offset(array_symbol)`
140+
remove_pointer_offsets(simplified_index, array_symbol);
141+
return index_exprt(array_symbol, simplified_index);
142+
}
143+
else if(src.id()==ID_index && to_index_expr(src).array().id()==ID_array)
144+
{
145+
// Case where the array is given by an array of expressions
146+
exprt index=to_index_expr(src).index();
147+
remove_pointer_offsets(index);
148+
149+
// We look for an actual integer value for the index
150+
std::size_t i;
151+
if(!simplify_index(index, i))
152+
return to_index_expr(src).array().operands()[i];
153+
}
154+
return src;
155+
}
156+
157+
/*******************************************************************\
158+
159+
Function: convert
160+
161+
Inputs:
162+
ns - a namespace
163+
goto_trace - a trace in a goto program
164+
dest - referecence to a json object in which the goto trace will
165+
be added
166+
167+
Outputs: none
168+
169+
Purpose: Produce a json representation of a trace.
170+
171+
\*******************************************************************/
172+
22173
void convert(
23174
const namespacet &ns,
24175
const goto_tracet &goto_trace,
@@ -84,7 +235,8 @@ void convert(
84235
json_objectt full_lhs_value;
85236

86237
assert(step.full_lhs.is_not_nil());
87-
full_lhs_string=from_expr(ns, identifier, step.full_lhs);
238+
exprt simplified=simplify_array_access(step.full_lhs);
239+
full_lhs_string=from_expr(ns, identifier, simplified);
88240

89241
const symbolt *symbol;
90242
irep_idt base_name, display_name;
@@ -98,7 +250,8 @@ void convert(
98250

99251
json_assignment["mode"]=json_stringt(id2string(symbol->mode));
100252
assert(step.full_lhs_value.is_not_nil());
101-
full_lhs_value=json(step.full_lhs_value, ns, symbol->mode);
253+
exprt simplified=simplify_array_access(step.full_lhs_value);
254+
full_lhs_value=json(simplified, ns, symbol->mode);
102255
}
103256
else
104257
{

0 commit comments

Comments
 (0)