Skip to content

Commit 5ce5cb4

Browse files
committed
Factor out object allocation code from object factories to util/allocate_objects.h/cpp
1 parent 5f55c33 commit 5ce5cb4

File tree

4 files changed

+383
-2
lines changed

4 files changed

+383
-2
lines changed

jbmc/src/java_bytecode/java_object_factory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Author: Daniel Kroening, [email protected]
7878
#include <util/std_code.h>
7979
#include <util/symbol_table.h>
8080

81-
/// Selects the kind of allocation used by java_object_factory et al.
81+
/// Selects the kind of allocation used by the object factories
8282
enum class allocation_typet
8383
{
8484
/// Allocate global objects

src/util/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
SRC = arith_tools.cpp \
1+
SRC = allocate_objects.cpp \
2+
arith_tools.cpp \
23
array_name.cpp \
34
base_type.cpp \
45
bv_arithmetic.cpp \

src/util/allocate_objects.cpp

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "allocate_objects.h"
10+
11+
#include "arith_tools.h"
12+
#include "c_types.h"
13+
#include "fresh_symbol.h"
14+
#include "pointer_offset_size.h"
15+
#include "string_constant.h"
16+
17+
/// Allocates a new object, either by creating a local variable with automatic
18+
/// lifetime, a global variable with static lifetime, or by dynamically
19+
/// allocating memory via ALLOCATE(). Code is added to `assignments` which
20+
/// assigns a pointer to the allocated memory to `target_expr`. The
21+
/// `allocate_type` may differ from `target_expr.type()`, e.g. for target_expr
22+
/// having type `int*` and `allocate_type` being an `int[10]`.
23+
///
24+
/// \param assignments: The code block to add code to.
25+
/// \param target_expr: A pointer to the allocated memory will be assigned to
26+
/// this lvalue expression
27+
/// \param allocate_type: Type of the object allocated
28+
/// \param lifetime: Lifetime of the allocated object (AUTOMATIC_LOCAL,
29+
/// STATIC_GLOBAL, or DYNAMIC)
30+
/// \param basename_prefix: prefix of the basename of the new variable
31+
/// \return An lvalue expression denoting the newly allocated object
32+
exprt allocate_objectst::allocate_object(
33+
code_blockt &assignments,
34+
const exprt &target_expr,
35+
const typet &allocate_type,
36+
const lifetimet lifetime,
37+
const irep_idt &basename_prefix)
38+
{
39+
switch(lifetime)
40+
{
41+
case lifetimet::AUTOMATIC_LOCAL:
42+
return allocate_automatic_local_object(
43+
assignments, target_expr, allocate_type, basename_prefix);
44+
break;
45+
46+
case lifetimet::STATIC_GLOBAL:
47+
return allocate_static_global_object(
48+
assignments, target_expr, allocate_type, basename_prefix);
49+
break;
50+
51+
case lifetimet::DYNAMIC:
52+
return allocate_dynamic_object(assignments, target_expr, allocate_type);
53+
break;
54+
}
55+
56+
UNREACHABLE;
57+
}
58+
59+
/// Creates a local variable with automatic lifetime. Code is added to
60+
/// `assignments` which assigns a pointer to the variable to `target_expr`. The
61+
/// `allocate_type` may differ from `target_expr.type()`, e.g. for `target_expr`
62+
/// having type `int*` and `allocate_type` being an `int[10]`..
63+
///
64+
/// \param assignments: The code block to add code to.
65+
/// \param target_expr: A pointer to the variable will be assigned to this
66+
/// lvalue expression
67+
/// \param allocate_type: Type of the new variable
68+
/// \param basename_prefix: prefix of the basename of the new variable
69+
/// \return An expression denoting the variable
70+
exprt allocate_objectst::allocate_automatic_local_object(
71+
code_blockt &assignments,
72+
const exprt &target_expr,
73+
const typet &allocate_type,
74+
const irep_idt &basename_prefix)
75+
{
76+
return allocate_non_dynamic_object(
77+
assignments, target_expr, allocate_type, false, basename_prefix);
78+
}
79+
80+
/// Creates a global variable with static lifetime. Code is added to
81+
/// `assignments` which assigns a pointer to the variable to `target_expr`. The
82+
/// `allocate_type` may differ from `target_expr.type()`, e.g. for `target_expr`
83+
/// having type `int*` and `allocate_type` being an `int[10]`.
84+
///
85+
/// \param assignments: The code block to add code to.
86+
/// \param target_expr: A pointer to the variable will be assigned to this
87+
/// lvalue expression
88+
/// \param allocate_type: Type of the new variable
89+
/// \param basename_prefix: prefix of the basename of the new variable
90+
/// \return An expression denoting the variable
91+
exprt allocate_objectst::allocate_static_global_object(
92+
code_blockt &assignments,
93+
const exprt &target_expr,
94+
const typet &allocate_type,
95+
const irep_idt &basename_prefix)
96+
{
97+
return allocate_non_dynamic_object(
98+
assignments, target_expr, allocate_type, true, basename_prefix);
99+
}
100+
101+
/// Creates a local variable with automatic lifetime and returns it as a symbol
102+
/// expression.
103+
///
104+
/// \param allocate_type: Type of the new variable
105+
/// \param basename_prefix: prefix of the basename of the new variable
106+
/// \return A symbol expression denoting the variable
107+
symbol_exprt allocate_objectst::allocate_automatic_local_object(
108+
const typet &allocate_type,
109+
const irep_idt &basename_prefix)
110+
{
111+
symbolt &aux_symbol = get_fresh_aux_symbol(
112+
allocate_type,
113+
id2string(name_prefix),
114+
id2string(basename_prefix),
115+
source_location,
116+
symbol_mode,
117+
symbol_table);
118+
119+
symbols_created.push_back(&aux_symbol);
120+
121+
return aux_symbol.symbol_expr();
122+
}
123+
124+
/// Generates code for allocating a dynamic object. A new variable with basename
125+
/// prefix `alloc_site` is introduced to which the allocated memory is assigned.
126+
/// Then, the variable is assigned to `target_expr`. For example, with
127+
/// `target_expr` being `*p` the following code is generated:
128+
///
129+
/// `alloc_site$1 = ALLOCATE(object_size, FALSE);`
130+
/// `*p = alloc_site$1;`
131+
///
132+
/// The function returns a dereference expressiont that dereferences the
133+
/// allocation site variable (e.g., `*alloc_site$1`) and which can be used to
134+
/// initialize the allocated memory.
135+
///
136+
/// \param output_code: Code block to which the necessary code is added
137+
/// \param target_expr: A pointer to the allocated memory will be assigned to
138+
/// this (lvalue) expression
139+
/// \param allocate_type: Type of the object allocated
140+
/// \return A dereference_exprt that dereferences the pointer to the allocated
141+
/// memory, or an empty expression when `allocate_type` is void
142+
exprt allocate_objectst::allocate_dynamic_object(
143+
code_blockt &output_code,
144+
const exprt &target_expr,
145+
const typet &allocate_type)
146+
{
147+
if(allocate_type.id() == ID_empty)
148+
{
149+
// make null
150+
null_pointer_exprt null_pointer_expr(to_pointer_type(target_expr.type()));
151+
code_assignt code(target_expr, null_pointer_expr);
152+
code.add_source_location() = source_location;
153+
output_code.add(code);
154+
155+
return exprt();
156+
}
157+
158+
// build size expression
159+
exprt object_size = size_of_expr(allocate_type, ns);
160+
INVARIANT(!object_size.is_nil(), "Size of objects should be known");
161+
162+
// malloc expression
163+
side_effect_exprt malloc_expr(
164+
ID_allocate, pointer_type(allocate_type), source_location);
165+
malloc_expr.copy_to_operands(object_size);
166+
malloc_expr.copy_to_operands(false_exprt());
167+
168+
// create a symbol for the malloc expression so we can initialize
169+
// without having to do it potentially through a double-deref, which
170+
// breaks the to-SSA phase.
171+
symbolt &malloc_sym = get_fresh_aux_symbol(
172+
pointer_type(allocate_type),
173+
id2string(name_prefix),
174+
"malloc_site",
175+
source_location,
176+
symbol_mode,
177+
symbol_table);
178+
179+
symbols_created.push_back(&malloc_sym);
180+
181+
code_assignt assign(malloc_sym.symbol_expr(), malloc_expr);
182+
assign.add_source_location() = source_location;
183+
output_code.add(assign);
184+
185+
exprt malloc_symbol_expr =
186+
ns.follow(malloc_sym.symbol_expr().type()) != ns.follow(target_expr.type())
187+
? (exprt)typecast_exprt(malloc_sym.symbol_expr(), target_expr.type())
188+
: malloc_sym.symbol_expr();
189+
190+
code_assignt code(target_expr, malloc_symbol_expr);
191+
code.add_source_location() = source_location;
192+
output_code.add(code);
193+
194+
return dereference_exprt(malloc_sym.symbol_expr());
195+
}
196+
197+
exprt allocate_objectst::allocate_non_dynamic_object(
198+
code_blockt &assignments,
199+
const exprt &target_expr,
200+
const typet &allocate_type,
201+
const bool static_lifetime,
202+
const irep_idt &basename_prefix)
203+
{
204+
symbolt &aux_symbol = get_fresh_aux_symbol(
205+
allocate_type,
206+
id2string(name_prefix),
207+
id2string(basename_prefix),
208+
source_location,
209+
symbol_mode,
210+
symbol_table);
211+
212+
aux_symbol.is_static_lifetime = static_lifetime;
213+
symbols_created.push_back(&aux_symbol);
214+
215+
exprt aoe =
216+
ns.follow(aux_symbol.symbol_expr().type()) !=
217+
ns.follow(target_expr.type().subtype())
218+
? (exprt)typecast_exprt(
219+
address_of_exprt(aux_symbol.symbol_expr()), target_expr.type())
220+
: address_of_exprt(aux_symbol.symbol_expr());
221+
222+
code_assignt code(target_expr, aoe);
223+
code.add_source_location() = source_location;
224+
assignments.add(code);
225+
226+
if(aoe.id() == ID_typecast)
227+
{
228+
return dereference_exprt(aoe);
229+
}
230+
else
231+
{
232+
return aux_symbol.symbol_expr();
233+
}
234+
}
235+
236+
/// Add a pointer to a symbol to the list of pointers to symbols created so far
237+
///
238+
/// \param symbol_ptr pointer to a symbol in the symbol table
239+
void allocate_objectst::add_created_symbol(const symbolt *symbol_ptr)
240+
{
241+
symbols_created.push_back(symbol_ptr);
242+
}
243+
244+
/// Adds declarations for all non-static symbols created
245+
///
246+
/// \param init_code code block to which to add the declarations
247+
void allocate_objectst::declare_created_symbols(code_blockt &init_code)
248+
{
249+
// Add the following code to init_code for each symbol that's been created:
250+
// <type> <identifier>;
251+
for(const symbolt *const symbol_ptr : symbols_created)
252+
{
253+
if(!symbol_ptr->is_static_lifetime)
254+
{
255+
code_declt decl(symbol_ptr->symbol_expr());
256+
decl.add_source_location() = source_location;
257+
init_code.add(decl);
258+
}
259+
}
260+
}
261+
262+
/// Adds code to mark the created symbols as input
263+
///
264+
/// \param init_code code block to which to add the generated code
265+
void allocate_objectst::mark_created_symbols_as_input(code_blockt &init_code)
266+
{
267+
// Add the following code to init_code for each symbol that's been created:
268+
// INPUT("<identifier>", <identifier>);
269+
for(symbolt const *symbol_ptr : symbols_created)
270+
{
271+
codet input_code(ID_input);
272+
input_code.operands().resize(2);
273+
input_code.op0() = address_of_exprt(
274+
index_exprt(
275+
string_constantt(symbol_ptr->base_name),
276+
from_integer(0, index_type())));
277+
input_code.op1() = symbol_ptr->symbol_expr();
278+
input_code.add_source_location() = source_location;
279+
init_code.add(std::move(input_code));
280+
}
281+
}

src/util/allocate_objects.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_UTIL_ALLOCATE_OBJECTS_H
10+
#define CPROVER_UTIL_ALLOCATE_OBJECTS_H
11+
12+
#include "base_type.h"
13+
#include "expr.h"
14+
#include "namespace.h"
15+
#include "source_location.h"
16+
#include "std_code.h"
17+
#include "symbol_table.h"
18+
#include "type.h"
19+
20+
/// Selects the kind of objects allocated
21+
enum class lifetimet
22+
{
23+
/// Allocate local objects with automatic lifetime
24+
AUTOMATIC_LOCAL,
25+
/// Allocate global objects with static lifetime
26+
STATIC_GLOBAL,
27+
/// Allocate dynamic objects (using ALLOCATE)
28+
DYNAMIC
29+
};
30+
31+
class allocate_objectst
32+
{
33+
public:
34+
allocate_objectst(
35+
const irep_idt &symbol_mode,
36+
const source_locationt &source_location,
37+
const irep_idt &name_prefix,
38+
symbol_table_baset &symbol_table)
39+
: symbol_mode(symbol_mode),
40+
source_location(source_location),
41+
name_prefix(name_prefix),
42+
symbol_table(symbol_table),
43+
ns(symbol_table)
44+
{
45+
}
46+
47+
exprt allocate_object(
48+
code_blockt &assignments,
49+
const exprt &target_expr,
50+
const typet &allocate_type,
51+
const lifetimet lifetime,
52+
const irep_idt &basename_prefix = "tmp");
53+
54+
exprt allocate_automatic_local_object(
55+
code_blockt &assignments,
56+
const exprt &target_expr,
57+
const typet &allocate_type,
58+
const irep_idt &basename_prefix = "tmp");
59+
60+
exprt allocate_static_global_object(
61+
code_blockt &assignments,
62+
const exprt &target_expr,
63+
const typet &allocate_type,
64+
const irep_idt &basename_prefix = "tmp");
65+
66+
exprt allocate_dynamic_object(
67+
code_blockt &output_code,
68+
const exprt &target_expr,
69+
const typet &allocate_type);
70+
71+
symbol_exprt allocate_automatic_local_object(
72+
const typet &allocate_type,
73+
const irep_idt &basename_prefix = "tmp");
74+
75+
void add_created_symbol(const symbolt *symbol_ptr);
76+
77+
void declare_created_symbols(code_blockt &init_code);
78+
79+
void mark_created_symbols_as_input(code_blockt &init_code);
80+
81+
private:
82+
const irep_idt &symbol_mode;
83+
const source_locationt &source_location;
84+
const irep_idt &name_prefix;
85+
86+
symbol_table_baset &symbol_table;
87+
const namespacet ns;
88+
89+
std::vector<const symbolt *> symbols_created;
90+
91+
exprt allocate_non_dynamic_object(
92+
code_blockt &assignments,
93+
const exprt &target_expr,
94+
const typet &allocate_type,
95+
const bool static_lifetime,
96+
const irep_idt &basename_prefix);
97+
};
98+
99+
#endif // CPROVER_UTIL_ALLOCATE_OBJECTS_H

0 commit comments

Comments
 (0)