CBMC
allocate_objects.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "allocate_objects.h"
10 
11 #include <util/c_types.h>
12 #include <util/fresh_symbol.h>
13 #include <util/pointer_expr.h>
15 #include <util/symbol.h>
16 
17 #include "goto_instruction_code.h"
18 
35  code_blockt &assignments,
36  const exprt &target_expr,
37  const typet &allocate_type,
38  const lifetimet lifetime,
39  const irep_idt &basename_prefix)
40 {
41  switch(lifetime)
42  {
45  assignments, target_expr, allocate_type, basename_prefix);
46  break;
47 
50  assignments, target_expr, allocate_type, basename_prefix);
51  break;
52 
53  case lifetimet::DYNAMIC:
54  return allocate_dynamic_object(assignments, target_expr, allocate_type);
55  break;
56  }
57 
59 }
60 
73  code_blockt &assignments,
74  const exprt &target_expr,
75  const typet &allocate_type,
76  const irep_idt &basename_prefix)
77 {
79  assignments, target_expr, allocate_type, false, basename_prefix);
80 }
81 
94  code_blockt &assignments,
95  const exprt &target_expr,
96  const typet &allocate_type,
97  const irep_idt &basename_prefix)
98 {
100  assignments, target_expr, allocate_type, true, basename_prefix);
101 }
102 
110  const typet &allocate_type,
111  const irep_idt &basename_prefix)
112 {
113  symbolt &aux_symbol = get_fresh_aux_symbol(
114  allocate_type,
116  id2string(basename_prefix),
118  symbol_mode,
119  symbol_table);
120 
121  add_created_symbol(aux_symbol);
122 
123  return aux_symbol.symbol_expr();
124 }
125 
127  code_blockt &output_code,
128  const exprt &target_expr,
129  const typet &allocate_type)
130 {
131  if(allocate_type.id() == ID_empty)
132  {
133  // make null
135  target_expr,
136  null_pointer_exprt{to_pointer_type(target_expr.type())},
138  output_code.add(std::move(code));
139 
140  return exprt();
141  }
142 
143  // build size expression
144  auto object_size = size_of_expr(allocate_type, ns);
145  INVARIANT(object_size.has_value(), "Size of objects should be known");
146 
147  // create a symbol for the malloc expression so we can initialize
148  // without having to do it potentially through a double-deref, which
149  // breaks the to-SSA phase.
150  symbolt &malloc_sym = get_fresh_aux_symbol(
151  pointer_type(allocate_type),
153  "malloc_site",
155  symbol_mode,
156  symbol_table);
157 
158  add_created_symbol(malloc_sym);
159 
160  code_frontend_assignt assign =
161  make_allocate_code(malloc_sym.symbol_expr(), object_size.value());
162  output_code.add(assign);
163 
164  exprt malloc_symbol_expr = typecast_exprt::conditional_cast(
165  malloc_sym.symbol_expr(), target_expr.type());
166 
167  code_frontend_assignt code(target_expr, malloc_symbol_expr);
169  output_code.add(code);
170 
171  return malloc_sym.symbol_expr();
172 }
173 
175  code_blockt &output_code,
176  const exprt &target_expr,
177  const typet &allocate_type)
178 {
179  return dereference_exprt(
180  allocate_dynamic_object_symbol(output_code, target_expr, allocate_type));
181 }
182 
184  code_blockt &assignments,
185  const exprt &target_expr,
186  const typet &allocate_type,
187  const bool static_lifetime,
188  const irep_idt &basename_prefix)
189 {
190  symbolt &aux_symbol = get_fresh_aux_symbol(
191  allocate_type,
193  id2string(basename_prefix),
195  symbol_mode,
196  symbol_table);
197 
198  aux_symbol.is_static_lifetime = static_lifetime;
199  add_created_symbol(aux_symbol);
200 
202  address_of_exprt(aux_symbol.symbol_expr()), target_expr.type());
203 
204  code_frontend_assignt code(target_expr, aoe);
206  assignments.add(code);
207 
208  if(aoe.id() == ID_typecast)
209  {
210  return dereference_exprt(aoe);
211  }
212  else
213  {
214  return aux_symbol.symbol_expr();
215  }
216 }
217 
222 {
223  symbols_created.push_back(symbol.name);
224 }
225 
230 {
231  // Add the following code to init_code for each symbol that's been created:
232  // <type> <identifier>;
233  for(const auto &symbol_id : symbols_created)
234  {
235  const symbolt &symbol = ns.lookup(symbol_id);
236  if(!symbol.is_static_lifetime)
237  {
238  code_frontend_declt decl{symbol.symbol_expr()};
240  init_code.add(decl);
241  }
242  }
243 }
244 
249 {
250  // Add the following code to init_code for each symbol that's been created:
251  // INPUT("<identifier>", <identifier>);
252  for(const auto &symbol_id : symbols_created)
253  {
254  const symbolt &symbol = ns.lookup(symbol_id);
255  init_code.add(
256  code_inputt{symbol.base_name, symbol.symbol_expr(), source_location});
257  }
258 }
259 
261 make_allocate_code(const symbol_exprt &lhs, const exprt &size)
262 {
263  side_effect_exprt alloc{
264  ID_allocate, {size, false_exprt()}, lhs.type(), lhs.source_location()};
265  return code_frontend_assignt(lhs, alloc);
266 }
code_frontend_assignt make_allocate_code(const symbol_exprt &lhs, const exprt &size)
Create code allocating an object of size size and assigning it to lhs
lifetimet
Selects the kind of objects allocated.
@ DYNAMIC
Allocate dynamic objects (using ALLOCATE)
@ STATIC_GLOBAL
Allocate global objects with static lifetime.
@ AUTOMATIC_LOCAL
Allocate local objects with automatic lifetime.
pointer_typet pointer_type(const typet &subtype)
Definition: c_types.cpp:235
Operator to return the address of an object.
Definition: pointer_expr.h:540
void add_created_symbol(const symbolt &symbol)
Add a pointer to a symbol to the list of pointers to symbols created so far.
exprt allocate_non_dynamic_object(code_blockt &assignments, const exprt &target_expr, const typet &allocate_type, const bool static_lifetime, const irep_idt &basename_prefix)
const namespacet ns
const irep_idt symbol_mode
std::vector< irep_idt > symbols_created
const irep_idt name_prefix
exprt allocate_object(code_blockt &assignments, const exprt &target_expr, const typet &allocate_type, const lifetimet lifetime, const irep_idt &basename_prefix="tmp")
Allocates a new object, either by creating a local variable with automatic lifetime,...
symbol_table_baset & symbol_table
const source_locationt source_location
exprt allocate_dynamic_object_symbol(code_blockt &output_code, const exprt &target_expr, const typet &allocate_type)
Generates code for allocating a dynamic object.
exprt allocate_dynamic_object(code_blockt &output_code, const exprt &target_expr, const typet &allocate_type)
Generate the same code as allocate_dynamic_object_symbol, but return a dereference_exprt that derefer...
exprt allocate_static_global_object(code_blockt &assignments, const exprt &target_expr, const typet &allocate_type, const irep_idt &basename_prefix="tmp")
Creates a global variable with static lifetime.
void mark_created_symbols_as_input(code_blockt &init_code)
Adds code to mark the created symbols as input.
exprt allocate_automatic_local_object(code_blockt &assignments, const exprt &target_expr, const typet &allocate_type, const irep_idt &basename_prefix="tmp")
Creates a local variable with automatic lifetime.
void declare_created_symbols(code_blockt &init_code)
Adds declarations for all non-static symbols created.
A codet representing sequential composition of program statements.
Definition: std_code.h:130
void add(const codet &code)
Definition: std_code.h:168
A codet representing an assignment in the program.
Definition: std_code.h:24
A codet representing the declaration of a local variable.
Definition: std_code.h:347
A goto_instruction_codet representing the declaration that an input of a particular description has a...
Operator to dereference a pointer.
Definition: pointer_expr.h:834
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
Base class for all expressions.
Definition: expr.h:56
source_locationt & add_source_location()
Definition: expr.h:236
const source_locationt & source_location() const
Definition: expr.h:231
typet & type()
Return the type of the expression.
Definition: expr.h:84
The Boolean constant false.
Definition: std_expr.h:3064
const irep_idt & id() const
Definition: irep.h:384
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
The null pointer constant.
Definition: pointer_expr.h:909
An expression containing a side effect.
Definition: std_code.h:1450
Expression to hold a symbol (variable)
Definition: std_expr.h:131
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
bool is_static_lifetime
Definition: symbol.h:70
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
irep_idt name
The unique identifier.
Definition: symbol.h:40
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
API to expression classes for Pointers.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
Pointer Logic.
exprt object_size(const exprt &pointer)
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
Symbol table entry.