@@ -14,11 +14,162 @@ Author: Daniel Kroening
14
14
#include < cassert>
15
15
16
16
#include < util/json_expr.h>
17
+ #include < util/arith_tools.h>
17
18
18
19
#include < langapi/language_util.h>
19
20
20
21
#include " json_goto_trace.h"
21
22
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
+
22
173
void convert (
23
174
const namespacet &ns,
24
175
const goto_tracet &goto_trace,
@@ -84,7 +235,8 @@ void convert(
84
235
json_objectt full_lhs_value;
85
236
86
237
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);
88
240
89
241
const symbolt *symbol;
90
242
irep_idt base_name, display_name;
@@ -98,7 +250,8 @@ void convert(
98
250
99
251
json_assignment[" mode" ]=json_stringt (id2string (symbol->mode ));
100
252
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 );
102
255
}
103
256
else
104
257
{
0 commit comments