CBMC
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 <unordered_set>
16 
17 #include <util/arith_tools.h>
18 #include <util/c_types.h>
19 #include <util/pointer_expr.h>
20 #include <util/std_expr.h>
21 
22 #include "abstract_environment.h"
23 
25 write_stackt::write_stackt() : stack(), top_stack(true)
26 {
27 }
28 
34  const exprt &expr,
35  const abstract_environmentt &environment,
36  const namespacet &ns)
37 {
38  top_stack = false;
39  if(expr.type().id() == ID_array)
40  {
41  // We are assigning an array to a pointer, which is equivalent to assigning
42  // the first element of that array
43  // &(expr)[0]
46  environment,
47  ns);
48  }
49  else
50  {
51  construct_stack_to_pointer(expr, environment, ns);
52  }
53 }
54 
60  const exprt &expr,
61  const abstract_environmentt &environment,
62  const namespacet &ns)
63 {
64  PRECONDITION(expr.type().id() == ID_pointer);
65 
66  if(expr.id() == ID_address_of)
67  {
68  // resovle reminder, can either be a symbol, member or index of
69  // otherwise unsupported
71  to_address_of_expr(expr).object(), environment, ns);
72  }
73  else if(expr.id() == ID_plus || expr.id() == ID_minus)
74  {
75  exprt base;
76  exprt offset;
77  const integral_resultt &which_side =
78  get_which_side_integral(expr, base, offset);
79  INVARIANT(
81  "An offset must be an integral amount");
82 
83  if(expr.id() == ID_minus)
84  {
85  // can't get a valid pointer by subtracting from a constant number
86  if(which_side == integral_resultt::LHS_INTEGRAL)
87  {
88  top_stack = true;
89  return;
90  }
91  offset = unary_minus_exprt(offset);
92  }
93 
94  abstract_object_pointert offset_value = environment.eval(offset, ns);
95 
97  std::make_shared<offset_entryt>(offset_value), environment, ns);
98 
99  // Build the pointer part
100  construct_stack_to_pointer(base, environment, ns);
101 
102  if(!top_stack)
103  {
104  // check the symbol at the bottom of the stack
105  const auto access = stack.front()->get_access_expr();
106  INVARIANT(
107  !access.second && access.first.id() == ID_symbol,
108  "The base should be an addressable location (i.e. symbol)");
109 
110  if(access.first.type().id() != ID_array)
111  {
112  top_stack = true;
113  }
114  }
115  }
116  else
117  {
118  // unknown expression type - play it safe and set to top
119  top_stack = true;
120  }
121 }
122 
129  const exprt &expr,
130  const abstract_environmentt &environment,
131  const namespacet &ns)
132 {
133  if(!top_stack)
134  {
135  if(expr.id() == ID_member)
136  {
137  add_to_stack(std::make_shared<simple_entryt>(expr), environment, ns);
139  to_member_expr(expr).struct_op(), environment, ns);
140  }
141  else if(expr.id() == ID_symbol || expr.id() == ID_dynamic_object)
142  {
143  add_to_stack(std::make_shared<simple_entryt>(expr), environment, ns);
144  }
145  else if(expr.id() == ID_index)
146  {
147  construct_stack_to_array_index(to_index_expr(expr), environment, ns);
148  }
149  else
150  {
151  top_stack = true;
152  }
153  }
154 }
155 
161  const index_exprt &index_expr,
162  const abstract_environmentt &environment,
163  const namespacet &ns)
164 {
165  abstract_object_pointert offset_value =
166  environment.eval(index_expr.index(), ns);
167 
168  add_to_stack(std::make_shared<offset_entryt>(offset_value), environment, ns);
169  construct_stack_to_lvalue(index_expr.array(), environment, ns);
170 }
171 
176 {
177  // A top stack is useless and its expression should not be evaluated
179  PRECONDITION(!stack.empty());
180  exprt access_expr = stack.front()->get_access_expr().first;
181  for(auto it = std::next(stack.begin()); it != stack.end(); ++it)
182  {
183  const auto access = (*it)->get_access_expr();
184  if(access.second)
185  access_expr = index_exprt{access_expr, access.first};
186  else
187  access_expr = access.first;
188  }
189  address_of_exprt top_expr(access_expr);
190  return std::move(top_expr);
191 }
192 
193 size_t write_stackt::depth() const
194 {
195  return stack.size();
196 }
197 
199 {
201  return stack[depth]->get_access_expr().first;
202 }
203 
205 {
207  auto const access = stack.back()->get_access_expr();
208 
209  if(access.second)
210  return access.first;
211 
212  if(access.first.id() == ID_member || access.first.id() == ID_symbol)
213  return access.first;
214 
215  if(access.first.id() == ID_index)
216  return to_index_expr(access.first).index();
217 
219 }
220 
225 {
226  return top_stack;
227 }
228 
235  std::shared_ptr<write_stack_entryt> entry_pointer,
236  const abstract_environmentt environment,
237  const namespacet &ns)
238 {
239  if(
240  stack.empty() ||
241  !stack.front()->try_squash_in(entry_pointer, environment, ns))
242  {
243  stack.insert(stack.begin(), entry_pointer);
244  }
245 }
246 
255  const exprt &expr,
256  exprt &out_base_expr,
257  exprt &out_integral_expr)
258 {
259  PRECONDITION(expr.operands().size() == 2);
260  const auto binary_e = to_binary_expr(expr);
261  static const std::unordered_set<irep_idt, irep_id_hash> integral_types = {
262  ID_signedbv, ID_unsignedbv, ID_integer};
263  if(integral_types.find(binary_e.lhs().type().id()) != integral_types.cend())
264  {
265  out_integral_expr = binary_e.lhs();
266  out_base_expr = binary_e.rhs();
268  }
269  else if(
270  integral_types.find(binary_e.rhs().type().id()) != integral_types.cend())
271  {
272  out_integral_expr = binary_e.rhs();
273  out_base_expr = binary_e.lhs();
275  }
276  else
277  {
278  out_integral_expr.make_nil();
279  out_base_expr.make_nil();
281  }
282 }
write_stackt::integral_resultt::LHS_INTEGRAL
@ LHS_INTEGRAL
write_stack.h
write_stackt::is_top_value
bool is_top_value() const
Is the stack representing an unknown value and hence can't be written to or read from.
Definition: write_stack.cpp:224
abstract_object_pointert
sharing_ptrt< class abstract_objectt > abstract_object_pointert
Definition: abstract_object.h:69
arith_tools.h
write_stackt::depth
size_t depth() const
Definition: write_stack.cpp:193
irept::make_nil
void make_nil()
Definition: irep.h:454
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
write_stackt::integral_resultt::RHS_INTEGRAL
@ RHS_INTEGRAL
abstract_environmentt
Definition: abstract_environment.h:40
exprt
Base class for all expressions.
Definition: expr.h:55
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
unsigned_long_int_type
unsignedbv_typet unsigned_long_int_type()
Definition: c_types.cpp:104
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
write_stackt::top_stack
bool top_stack
Definition: write_stack.h:72
write_stackt::target_expression
exprt target_expression(size_t depth) const
Definition: write_stack.cpp:198
write_stackt::construct_stack_to_lvalue
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.
Definition: write_stack.cpp:128
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
pointer_expr.h
abstract_environment.h
signed_size_type
signedbv_typet signed_size_type()
Definition: c_types.cpp:84
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
unary_minus_exprt
The unary minus expression.
Definition: std_expr.h:422
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
abstract_environmentt::eval
virtual abstract_object_pointert eval(const exprt &expr, const namespacet &ns) const
These three are really the heart of the method.
Definition: abstract_environment.cpp:94
irept::id
const irep_idt & id() const
Definition: irep.h:396
write_stackt::construct_stack_to_pointer
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.
Definition: write_stack.cpp:59
write_stackt::offset_expression
exprt offset_expression() const
Definition: write_stack.cpp:204
write_stackt::get_which_side_integral
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,...
Definition: write_stack.cpp:254
write_stackt::construct_stack_to_array_index
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.
Definition: write_stack.cpp:160
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
write_stackt::integral_resultt::NEITHER_INTEGRAL
@ NEITHER_INTEGRAL
to_address_of_expr
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:408
exprt::operands
operandst & operands()
Definition: expr.h:94
index_exprt
Array index operator.
Definition: std_expr.h:1409
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
write_stackt::integral_resultt
integral_resultt
Definition: write_stack.h:59
write_stackt::write_stackt
write_stackt()
Build a topstack.
Definition: write_stack.cpp:25
write_stackt::add_to_stack
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.
Definition: write_stack.cpp:234
write_stackt::to_expression
exprt to_expression() const
Convert the stack to an expression that can be used to write to.
Definition: write_stack.cpp:175
std_expr.h
write_stackt::stack
continuation_stack_storet stack
Definition: write_stack.h:71
c_types.h
validation_modet::INVARIANT
@ INVARIANT