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