1515#include < util/std_expr.h>
1616#include < util/cprover_prefix.h>
1717#include < util/base_type.h>
18-
18+ # include < util/pointer_offset_size.h >
1919#include < util/c_types.h>
2020
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.
8925void goto_symext::process_array_expr (exprt &expr)
9026{
9127 // This may change the type of the expression!
@@ -94,41 +30,28 @@ void goto_symext::process_array_expr(exprt &expr)
9430 {
9531 if_exprt &if_expr=to_if_expr (expr);
9632 process_array_expr (if_expr.true_case ());
33+ process_array_expr (if_expr.false_case ());
9734
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+ }
10045
10146 if_expr.type ()=if_expr.true_case ().type ();
10247 }
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- }
11748 else if (expr.id ()==ID_address_of)
11849 {
11950 // strip
12051 exprt tmp=to_address_of_expr (expr).op0 ();
12152 expr.swap (tmp);
12253 process_array_expr (expr);
12354 }
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- }
13255 else if (expr.id ()==ID_symbol &&
13356 expr.get_bool (ID_C_SSA_symbol) &&
13457 to_ssa_expr (expr).get_original_expr ().id ()==ID_index)
@@ -137,10 +60,58 @@ void goto_symext::process_array_expr(exprt &expr)
13760 const index_exprt &index_expr=to_index_expr (ssa.get_original_expr ());
13861 exprt tmp=index_expr.array ();
13962 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+ }
140114 }
141- else
142- Forall_operands (it, expr)
143- process_array_expr (*it);
144115}
145116
146117// / Rewrite index/member expressions in byte_extract to offset
0 commit comments