@@ -14,11 +14,112 @@ 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
+ // / Replaces in src, expressions of the form pointer_offset(constant) by that
24
+ // / constant.
25
+ // / \param src: an expression
26
+ void remove_pointer_offsets (exprt &src)
27
+ {
28
+ if (src.id ()==ID_pointer_offset && src.op0 ().id ()==ID_constant)
29
+ src=src.op0 ();
30
+ else
31
+ for (auto &op : src.operands ())
32
+ remove_pointer_offsets (op);
33
+ }
34
+
35
+ // / Replaces in src, expressions of the form pointer_offset(array_symbol) by a
36
+ // / constant value of 0. This is meant to simplify array expressions.
37
+ // / \param src: an expression
38
+ // / \param array_symbol: a symbol expression representing an array
39
+ void remove_pointer_offsets (exprt &src, const symbol_exprt &array_symbol)
40
+ {
41
+ if (src.id ()==ID_pointer_offset &&
42
+ src.op0 ().id ()==ID_constant &&
43
+ src.op0 ().op0 ().id ()==ID_address_of &&
44
+ src.op0 ().op0 ().op0 ().id ()==ID_index)
45
+ {
46
+ const index_exprt &idx=to_index_expr (src.op0 ().op0 ().op0 ());
47
+ const irep_idt &array_id=to_symbol_expr (idx.array ()).get_identifier ();
48
+ if (idx.array ().id ()==ID_symbol &&
49
+ array_id==array_symbol.get_identifier () &&
50
+ to_constant_expr (idx.index ()).value_is_zero_string ())
51
+ src=from_integer (0 , src.type ());
52
+ }
53
+ else
54
+ for (auto &op : src.operands ())
55
+ remove_pointer_offsets (op, array_symbol);
56
+ }
57
+
58
+ // / Simplify the expression in index as much as possible to try to get an
59
+ // / unsigned constant.
60
+ // / \param idx: an expression representing an index in an array
61
+ // / \param out: a reference to an unsigned value of type size_t, which will hold
62
+ // / the result of the simplification if it is successful
63
+ // / \return Boolean flag that is true if the `idx` expression could not be
64
+ // / simplified into a unsigned constant value.
65
+ bool simplify_index (const exprt &idx, std::size_t &out)
66
+ {
67
+ if (idx.id ()==ID_constant)
68
+ {
69
+ std::string value_str (id2string (to_constant_expr (idx).get_value ()));
70
+ mp_integer int_value=binary2integer (value_str, false );
71
+ if (int_value>std::numeric_limits<std::size_t >::max ())
72
+ return true ;
73
+ out=int_value.to_long ();
74
+ return false ;
75
+ }
76
+ else if (idx.id ()==ID_plus)
77
+ {
78
+ std::size_t l, r;
79
+ if (!simplify_index (idx.op0 (), l) && !simplify_index (idx.op1 (), r))
80
+ {
81
+ out=l+r;
82
+ return false ;
83
+ }
84
+ }
85
+
86
+ return true ;
87
+ }
88
+
89
+ // / Simplify an expression before putting it in the json format
90
+ // / \param src: an expression potentialy containing array accesses (index_expr)
91
+ // / \return an expression similar in meaning to src but where array accesses
92
+ // / have been simplified
93
+ exprt simplify_array_access (const exprt &src)
94
+ {
95
+ if (src.id ()==ID_index && to_index_expr (src).array ().id ()==ID_symbol)
96
+ {
97
+ // Case where the array is a symbol.
98
+ const symbol_exprt &array_symbol=to_symbol_expr (to_index_expr (src).array ());
99
+ exprt simplified_index=to_index_expr (src).index ();
100
+ // We remove potential appearances of `pointer_offset(array_symbol)`
101
+ remove_pointer_offsets (simplified_index, array_symbol);
102
+ return index_exprt (array_symbol, simplified_index);
103
+ }
104
+ else if (src.id ()==ID_index && to_index_expr (src).array ().id ()==ID_array)
105
+ {
106
+ // Case where the array is given by an array of expressions
107
+ exprt index =to_index_expr (src).index ();
108
+ remove_pointer_offsets (index );
109
+
110
+ // We look for an actual integer value for the index
111
+ std::size_t i;
112
+ if (!simplify_index (index , i))
113
+ return to_index_expr (src).array ().operands ()[i];
114
+ }
115
+ return src;
116
+ }
117
+
118
+ // / Produce a json representation of a trace.
119
+ // / \param ns: a namespace
120
+ // / \param goto_trace: a trace in a goto program
121
+ // / \param dest: referecence to a json object in which the goto trace will be
122
+ // / added
22
123
void convert (
23
124
const namespacet &ns,
24
125
const goto_tracet &goto_trace,
@@ -84,7 +185,8 @@ void convert(
84
185
json_objectt full_lhs_value;
85
186
86
187
assert (step.full_lhs .is_not_nil ());
87
- full_lhs_string=from_expr (ns, identifier, step.full_lhs );
188
+ exprt simplified=simplify_array_access (step.full_lhs );
189
+ full_lhs_string=from_expr (ns, identifier, simplified);
88
190
89
191
const symbolt *symbol;
90
192
irep_idt base_name, display_name;
@@ -98,7 +200,8 @@ void convert(
98
200
99
201
json_assignment[" mode" ]=json_stringt (id2string (symbol->mode ));
100
202
assert (step.full_lhs_value .is_not_nil ());
101
- full_lhs_value=json (step.full_lhs_value , ns, symbol->mode );
203
+ exprt simplified=simplify_array_access (step.full_lhs_value );
204
+ full_lhs_value=json (simplified, ns, symbol->mode );
102
205
}
103
206
else
104
207
{
0 commit comments