15
15
#include < util/std_expr.h>
16
16
#include < util/cprover_prefix.h>
17
17
#include < util/base_type.h>
18
-
18
+ # include < util/pointer_offset_size.h >
19
19
#include < util/c_types.h>
20
20
21
- void goto_symext::process_array_expr_rec (
22
- exprt &expr,
23
- const typet &type) const
24
- {
25
- if (expr.id ()==ID_if)
26
- {
27
- if_exprt &if_expr=to_if_expr (expr);
28
- process_array_expr_rec (if_expr.true_case (), type);
29
- process_array_expr_rec (if_expr.false_case (), type);
30
- }
31
- else if (expr.id ()==ID_index)
32
- {
33
- // strip index
34
- index_exprt &index_expr=to_index_expr (expr);
35
- exprt tmp=index_expr.array ();
36
- expr.swap (tmp);
37
- }
38
- else if (expr.id ()==ID_typecast)
39
- {
40
- // strip
41
- exprt tmp=to_typecast_expr (expr).op0 ();
42
- expr.swap (tmp);
43
- process_array_expr_rec (expr, type);
44
- }
45
- else if (expr.id ()==ID_address_of)
46
- {
47
- // strip
48
- exprt tmp=to_address_of_expr (expr).op0 ();
49
- expr.swap (tmp);
50
- process_array_expr_rec (expr, type);
51
- }
52
- else if (expr.id ()==ID_byte_extract_little_endian ||
53
- expr.id ()==ID_byte_extract_big_endian)
54
- {
55
- // pick the root object
56
- exprt tmp=to_byte_extract_expr (expr).op ();
57
- expr.swap (tmp);
58
- process_array_expr_rec (expr, type);
59
- }
60
- else if (expr.id ()==ID_symbol &&
61
- expr.get_bool (ID_C_SSA_symbol) &&
62
- to_ssa_expr (expr).get_original_expr ().id ()==ID_index)
63
- {
64
- const ssa_exprt &ssa=to_ssa_expr (expr);
65
- const index_exprt &index_expr=to_index_expr (ssa.get_original_expr ());
66
- exprt tmp=index_expr.array ();
67
- expr.swap (tmp);
68
- }
69
- else
70
- {
71
- Forall_operands (it, expr)
72
- {
73
- typet t=it->type ();
74
- process_array_expr_rec (*it, t);
75
- }
76
- }
77
-
78
- if (!base_type_eq (expr.type (), type, ns))
79
- {
80
- byte_extract_exprt be (byte_extract_id ());
81
- be.type ()=type;
82
- be.op ()=expr;
83
- be.offset ()=from_integer (0 , index_type ());
84
-
85
- expr.swap (be);
86
- }
87
- }
88
-
21
+ // / Given an expression, find the root object and the offset into it.
22
+ // /
23
+ // / The extra complication to be considered here is that the expression may
24
+ // / have any number of ternary expressions mixed with type casts.
89
25
void goto_symext::process_array_expr (exprt &expr)
90
26
{
91
27
// This may change the type of the expression!
@@ -94,41 +30,28 @@ void goto_symext::process_array_expr(exprt &expr)
94
30
{
95
31
if_exprt &if_expr=to_if_expr (expr);
96
32
process_array_expr (if_expr.true_case ());
33
+ process_array_expr (if_expr.false_case ());
97
34
98
- process_array_expr_rec (if_expr.false_case (),
99
- if_expr.true_case ().type ());
35
+ if (!base_type_eq (if_expr.true_case (), if_expr.false_case (), ns))
36
+ {
37
+ byte_extract_exprt be (
38
+ byte_extract_id (),
39
+ if_expr.false_case (),
40
+ from_integer (0 , index_type ()),
41
+ if_expr.true_case ().type ());
42
+
43
+ if_expr.false_case ().swap (be);
44
+ }
100
45
101
46
if_expr.type ()=if_expr.true_case ().type ();
102
47
}
103
- else if (expr.id ()==ID_index)
104
- {
105
- // strip index
106
- index_exprt &index_expr=to_index_expr (expr);
107
- exprt tmp=index_expr.array ();
108
- expr.swap (tmp);
109
- }
110
- else if (expr.id ()==ID_typecast)
111
- {
112
- // strip
113
- exprt tmp=to_typecast_expr (expr).op0 ();
114
- expr.swap (tmp);
115
- process_array_expr (expr);
116
- }
117
48
else if (expr.id ()==ID_address_of)
118
49
{
119
50
// strip
120
51
exprt tmp=to_address_of_expr (expr).op0 ();
121
52
expr.swap (tmp);
122
53
process_array_expr (expr);
123
54
}
124
- else if (expr.id ()==ID_byte_extract_little_endian ||
125
- expr.id ()==ID_byte_extract_big_endian)
126
- {
127
- // pick the root object
128
- exprt tmp=to_byte_extract_expr (expr).op ();
129
- expr.swap (tmp);
130
- process_array_expr (expr);
131
- }
132
55
else if (expr.id ()==ID_symbol &&
133
56
expr.get_bool (ID_C_SSA_symbol) &&
134
57
to_ssa_expr (expr).get_original_expr ().id ()==ID_index)
@@ -137,10 +60,58 @@ void goto_symext::process_array_expr(exprt &expr)
137
60
const index_exprt &index_expr=to_index_expr (ssa.get_original_expr ());
138
61
exprt tmp=index_expr.array ();
139
62
expr.swap (tmp);
63
+
64
+ process_array_expr (expr);
65
+ }
66
+ else if (expr.id () != ID_symbol)
67
+ {
68
+ object_descriptor_exprt ode;
69
+ ode.build (expr, ns);
70
+ do_simplify (ode.offset ());
71
+
72
+ expr = ode.root_object ();
73
+
74
+ if (!ode.offset ().is_zero ())
75
+ {
76
+ if (expr.type ().id () != ID_array)
77
+ {
78
+ exprt array_size = size_of_expr (expr.type (), ns);
79
+ do_simplify (array_size);
80
+ expr =
81
+ byte_extract_exprt (
82
+ byte_extract_id (),
83
+ expr,
84
+ from_integer (0 , index_type ()),
85
+ array_typet (char_type (), array_size));
86
+ }
87
+
88
+ // given an array type T[N], i.e., an array of N elements of type T, and a
89
+ // byte offset B, compute the array offset B/sizeof(T) and build a new
90
+ // type T[N-(B/sizeof(T))]
91
+ const array_typet &prev_array_type = to_array_type (expr.type ());
92
+ const typet &array_size_type = prev_array_type.size ().type ();
93
+ const typet &subtype = prev_array_type.subtype ();
94
+
95
+ exprt new_offset (ode.offset ());
96
+ if (new_offset.type () != array_size_type)
97
+ new_offset.make_typecast (array_size_type);
98
+ exprt subtype_size = size_of_expr (subtype, ns);
99
+ if (subtype_size.type () != array_size_type)
100
+ subtype_size.make_typecast (array_size_type);
101
+ new_offset = div_exprt (new_offset, subtype_size);
102
+ minus_exprt new_size (prev_array_type.size (), new_offset);
103
+ do_simplify (new_size);
104
+
105
+ array_typet new_array_type (subtype, new_size);
106
+
107
+ expr =
108
+ byte_extract_exprt (
109
+ byte_extract_id (),
110
+ expr,
111
+ ode.offset (),
112
+ new_array_type);
113
+ }
140
114
}
141
- else
142
- Forall_operands (it, expr)
143
- process_array_expr (*it);
144
115
}
145
116
146
117
// / Rewrite index/member expressions in byte_extract to offset
0 commit comments