CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
write_stack.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3 Module: Variable Sensitivity Domain
4
5 Author: DiffBlue Limited.
6
7\*******************************************************************/
8
12
13#include "write_stack.h"
14
15#include <util/arith_tools.h>
16#include <util/c_types.h>
17#include <util/pointer_expr.h>
18#include <util/std_expr.h>
19
21#include "write_stack_entry.h"
22
23#include <unordered_set>
24
26write_stackt::write_stackt() : stack(), top_stack(true)
27{
28}
29
35 const exprt &expr,
36 const abstract_environmentt &environment,
37 const namespacet &ns)
38{
39 top_stack = false;
40 if(expr.type().id() == ID_array)
41 {
42 // We are assigning an array to a pointer, which is equivalent to assigning
43 // the first element of that array
44 // &(expr)[0]
47 environment,
48 ns);
49 }
50 else
51 {
52 construct_stack_to_pointer(expr, environment, ns);
53 }
54}
55
61 const exprt &expr,
62 const abstract_environmentt &environment,
63 const namespacet &ns)
64{
65 PRECONDITION(expr.type().id() == ID_pointer);
66
67 if(expr.id() == ID_address_of)
68 {
69 // resovle reminder, can either be a symbol, member or index of
70 // otherwise unsupported
72 to_address_of_expr(expr).object(), environment, ns);
73 }
74 else if(expr.id() == ID_plus || expr.id() == ID_minus)
75 {
76 exprt base;
77 exprt offset;
79 get_which_side_integral(expr, base, offset);
82 "An offset must be an integral amount");
83
84 if(expr.id() == ID_minus)
85 {
86 // can't get a valid pointer by subtracting from a constant number
88 {
89 top_stack = true;
90 return;
91 }
92 offset = unary_minus_exprt(offset);
93 }
94
95 abstract_object_pointert offset_value = environment.eval(offset, ns);
96
98 std::make_shared<offset_entryt>(offset_value), environment, ns);
99
100 // Build the pointer part
101 construct_stack_to_pointer(base, environment, ns);
102
103 if(!top_stack)
104 {
105 // check the symbol at the bottom of the stack
106 const auto access = stack.front()->get_access_expr();
107 INVARIANT(
108 !access.second && access.first.id() == ID_symbol,
109 "The base should be an addressable location (i.e. symbol)");
110
111 if(access.first.type().id() != ID_array)
112 {
113 top_stack = true;
114 }
115 }
116 }
117 else
118 {
119 // unknown expression type - play it safe and set to top
120 top_stack = true;
121 }
122}
123
130 const exprt &expr,
131 const abstract_environmentt &environment,
132 const namespacet &ns)
133{
134 if(!top_stack)
135 {
136 if(expr.id() == ID_member)
137 {
138 add_to_stack(std::make_shared<simple_entryt>(expr), environment, ns);
140 to_member_expr(expr).struct_op(), environment, ns);
141 }
142 else if(expr.id() == ID_symbol || expr.id() == ID_dynamic_object)
143 {
144 add_to_stack(std::make_shared<simple_entryt>(expr), environment, ns);
145 }
146 else if(expr.id() == ID_index)
147 {
148 construct_stack_to_array_index(to_index_expr(expr), environment, ns);
149 }
150 else
151 {
152 top_stack = true;
153 }
154 }
155}
156
162 const index_exprt &index_expr,
163 const abstract_environmentt &environment,
164 const namespacet &ns)
165{
167 environment.eval(index_expr.index(), ns);
168
169 add_to_stack(std::make_shared<offset_entryt>(offset_value), environment, ns);
170 construct_stack_to_lvalue(index_expr.array(), environment, ns);
171}
172
177{
178 // A top stack is useless and its expression should not be evaluated
180 PRECONDITION(!stack.empty());
181 exprt access_expr = stack.front()->get_access_expr().first;
182 for(auto it = std::next(stack.begin()); it != stack.end(); ++it)
183 {
184 const auto access = (*it)->get_access_expr();
185 if(access.second)
187 else
188 access_expr = access.first;
189 }
191 return std::move(top_expr);
192}
193
195{
196 return stack.size();
197}
198
200{
202 return stack[depth]->get_access_expr().first;
203}
204
206{
208 auto const access = stack.back()->get_access_expr();
209
210 if(access.second)
211 return access.first;
212
213 if(access.first.id() == ID_member || access.first.id() == ID_symbol)
214 return access.first;
215
216 if(access.first.id() == ID_index)
217 return to_index_expr(access.first).index();
218
220}
221
226{
227 return top_stack;
228}
229
236 std::shared_ptr<write_stack_entryt> entry_pointer,
237 const abstract_environmentt environment,
238 const namespacet &ns)
239{
240 if(
241 stack.empty() ||
242 !stack.front()->try_squash_in(entry_pointer, environment, ns))
243 {
244 stack.insert(stack.begin(), entry_pointer);
245 }
246}
247
256 const exprt &expr,
259{
260 PRECONDITION(expr.operands().size() == 2);
261 const auto binary_e = to_binary_expr(expr);
262 static const std::unordered_set<irep_idt, irep_id_hash> integral_types = {
264 if(integral_types.find(binary_e.lhs().type().id()) != integral_types.cend())
265 {
267 out_base_expr = binary_e.rhs();
269 }
270 else if(
271 integral_types.find(binary_e.rhs().type().id()) != integral_types.cend())
272 {
274 out_base_expr = binary_e.lhs();
276 }
277 else
278 {
279 out_integral_expr.make_nil();
280 out_base_expr.make_nil();
282 }
283}
An abstract version of a program environment.
sharing_ptrt< class abstract_objectt > abstract_object_pointert
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
unsignedbv_typet unsigned_long_int_type()
Definition c_types.cpp:86
signedbv_typet signed_size_type()
Definition c_types.cpp:66
virtual abstract_object_pointert eval(const exprt &expr, const namespacet &ns) const
These three are really the heart of the method.
Operator to return the address of an object.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
Array index operator.
Definition std_expr.h:1470
const irep_idt & id() const
Definition irep.h:388
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
The unary minus expression.
Definition std_expr.h:484
void construct_stack_to_array_index(const index_exprt &expr, const abstract_environmentt &environment, const namespacet &ns)
Construct a stack for an array position l-value.
exprt target_expression(size_t depth) const
exprt offset_expression() const
static integral_resultt get_which_side_integral(const exprt &expr, exprt &out_base_expr, exprt &out_integral_expr)
Utility function to find out which side of a binary operation has an integral type,...
void construct_stack_to_lvalue(const exprt &expr, const abstract_environmentt &environment, const namespacet &ns)
Construct a stack up to a specific l-value (i.e.
write_stackt()
Build a topstack.
bool is_top_value() const
Is the stack representing an unknown value and hence can't be written to or read from.
exprt to_expression() const
Convert the stack to an expression that can be used to write to.
void construct_stack_to_pointer(const exprt &expr, const abstract_environmentt &environment, const namespacet &ns)
Add to the stack the elements to get to a pointer.
size_t depth() const
continuation_stack_storet stack
Definition write_stack.h:78
void add_to_stack(std::shared_ptr< write_stack_entryt > entry_pointer, const abstract_environmentt environment, const namespacet &ns)
Add an element to the top of the stack.
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:715
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
Represents a stack of write operations to an addressable memory location.
Represents an entry in the write_stackt.