Skip to content

Commit 32e4ac7

Browse files
author
Joel Allred
committed
Factor loop init out of gen_nondet_array_init
Makes gen_nondet_array_init smaller and clarifies process.
1 parent f887a99 commit 32e4ac7

File tree

1 file changed

+111
-44
lines changed

1 file changed

+111
-44
lines changed

jbmc/src/java_bytecode/java_object_factory.cpp

Lines changed: 111 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ class java_object_factoryt
166166
code_blockt &assignments,
167167
const exprt &instance_expr,
168168
const irep_idt &method_name);
169+
170+
void array_loop_init_code(
171+
code_blockt &assignments,
172+
const exprt &init_array_expr,
173+
const exprt &length_expr,
174+
const typet &element_type,
175+
const exprt &max_length_expr,
176+
size_t depth,
177+
update_in_placet update_in_place,
178+
const source_locationt &location);
169179
};
170180

171181
/// Returns a codet that assigns \p expr, of type \p ptr_type, a NULL value.
@@ -1210,55 +1220,51 @@ codet make_allocate_code(const symbol_exprt &lhs, const exprt &size)
12101220
return code_assignt(lhs, alloc);
12111221
}
12121222

1213-
/// Create code to initialize a Java array whose size will be at most
1214-
/// `max_nondet_array_length`. The code is emitted to \p assignments does as
1215-
/// follows:
1216-
/// 1. non-deterministically choose a length for the array
1217-
/// 2. assume that such length is >=0 and <= max_length
1218-
/// 3. loop through all elements of the array and initialize them
1219-
void java_object_factoryt::gen_nondet_array_init(
1223+
/// Create code to nondeterministically initialise each element of an array in a
1224+
/// loop.
1225+
/// The code produced is of the form (supposing an array of type OBJ):
1226+
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1227+
/// struct java.lang.Integer **array_data_init;
1228+
/// int array_init_iter;
1229+
/// array_data_init = (struct OBJ **)init_array_expr;
1230+
/// array_init_iter = 0;
1231+
/// 2: IF array_init_iter == length_expr THEN GOTO 5
1232+
/// IF array_init_iter == max_length_expr THEN GOTO 5
1233+
/// IF !NONDET(__CPROVER_bool) THEN GOTO 3
1234+
/// array_data_init[array_init_iter] = null;
1235+
/// GOTO 4
1236+
/// 3: malloc_site = ALLOCATE(...);
1237+
/// array_data_init[array_init_iter] = (struct OBJ *)malloc_site;
1238+
/// *malloc_site = {...};
1239+
/// malloc_site->value = NONDET(int);
1240+
/// 4: array_init_iter = array_init_iter + 1;
1241+
/// GOTO 2
1242+
/// 5: ...
1243+
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1244+
/// \param [out] assignments : Code block to which the initializing assignments
1245+
/// will be appended.
1246+
/// \param init_array_expr : array data
1247+
/// \param length_expr : array length
1248+
/// \param element_type: type of array elements
1249+
/// \param max_length_expr : max length, as specified by max-nondet-array-length
1250+
/// \param depth: Number of times that a pointer has been dereferenced from the
1251+
/// root of the object tree that we are initializing.
1252+
/// \param update_in_place:
1253+
/// NO_UPDATE_IN_PLACE: initialize `expr` from scratch
1254+
/// MAY_UPDATE_IN_PLACE: generate a runtime nondet branch between the NO_
1255+
/// and MUST_ cases.
1256+
/// MUST_UPDATE_IN_PLACE: reinitialize an existing object
1257+
/// \param location: Source location associated with nondet-initialization.
1258+
void java_object_factoryt::array_loop_init_code(
12201259
code_blockt &assignments,
1221-
const exprt &expr,
1260+
const exprt &init_array_expr,
1261+
const exprt &length_expr,
1262+
const typet &element_type,
1263+
const exprt &max_length_expr,
12221264
size_t depth,
12231265
update_in_placet update_in_place,
12241266
const source_locationt &location)
12251267
{
1226-
PRECONDITION(expr.type().id()==ID_pointer);
1227-
PRECONDITION(expr.type().subtype().id() == ID_struct_tag);
1228-
PRECONDITION(update_in_place!=update_in_placet::MAY_UPDATE_IN_PLACE);
1229-
1230-
const typet &type=ns.follow(expr.type().subtype());
1231-
const struct_typet &struct_type=to_struct_type(type);
1232-
const typet &element_type =
1233-
static_cast<const typet &>(expr.type().subtype().find(ID_element_type));
1234-
1235-
auto max_length_expr=from_integer(
1236-
object_factory_parameters.max_nondet_array_length, java_int_type());
1237-
1238-
// In NO_UPDATE_IN_PLACE mode we allocate a new array and recursively
1239-
// initialize its elements
1240-
if(update_in_place==update_in_placet::NO_UPDATE_IN_PLACE)
1241-
{
1242-
allocate_nondet_length_array(
1243-
assignments, expr, max_length_expr, element_type, location);
1244-
}
1245-
1246-
// Otherwise we're updating the array in place, and use the
1247-
// existing array allocation and length.
1248-
1249-
INVARIANT(
1250-
is_valid_java_array(struct_type),
1251-
"Java struct array does not conform to expectations");
1252-
1253-
dereference_exprt deref_expr(expr, expr.type().subtype());
1254-
const auto &comps=struct_type.components();
1255-
const member_exprt length_expr(deref_expr, "length", comps[1].type());
1256-
exprt init_array_expr=member_exprt(deref_expr, "data", comps[2].type());
1257-
1258-
if(init_array_expr.type()!=pointer_type(element_type))
1259-
init_array_expr=
1260-
typecast_exprt(init_array_expr, pointer_type(element_type));
1261-
12621268
const symbol_exprt &array_init_symexpr =
12631269
allocate_objects.allocate_automatic_local_object(
12641270
init_array_expr.type(), "array_data_init");
@@ -1334,6 +1340,67 @@ void java_object_factoryt::gen_nondet_array_init(
13341340
assignments.add(std::move(init_done_label));
13351341
}
13361342

1343+
/// Create code to initialize a Java array whose size will be at most
1344+
/// `max_nondet_array_length`. The code is emitted to \p assignments does as
1345+
/// follows:
1346+
/// 1. non-deterministically choose a length for the array
1347+
/// 2. assume that such length is >=0 and <= max_length
1348+
/// 3. loop through all elements of the array and initialize them
1349+
void java_object_factoryt::gen_nondet_array_init(
1350+
code_blockt &assignments,
1351+
const exprt &expr,
1352+
size_t depth,
1353+
update_in_placet update_in_place,
1354+
const source_locationt &location)
1355+
{
1356+
PRECONDITION(expr.type().id() == ID_pointer);
1357+
PRECONDITION(expr.type().subtype().id() == ID_struct_tag);
1358+
PRECONDITION(update_in_place != update_in_placet::MAY_UPDATE_IN_PLACE);
1359+
1360+
const typet &type = ns.follow(expr.type().subtype());
1361+
const struct_typet &struct_type = to_struct_type(type);
1362+
const typet &element_type =
1363+
static_cast<const typet &>(expr.type().subtype().find(ID_element_type));
1364+
1365+
auto max_length_expr = from_integer(
1366+
object_factory_parameters.max_nondet_array_length, java_int_type());
1367+
1368+
// In NO_UPDATE_IN_PLACE mode we allocate a new array and recursively
1369+
// initialize its elements
1370+
if(update_in_place == update_in_placet::NO_UPDATE_IN_PLACE)
1371+
{
1372+
allocate_nondet_length_array(
1373+
assignments, expr, max_length_expr, element_type, location);
1374+
}
1375+
1376+
// Otherwise we're updating the array in place, and use the
1377+
// existing array allocation and length.
1378+
1379+
INVARIANT(
1380+
is_valid_java_array(struct_type),
1381+
"Java struct array does not conform to expectations");
1382+
1383+
dereference_exprt deref_expr(expr, expr.type().subtype());
1384+
const auto &comps = struct_type.components();
1385+
const member_exprt length_expr(deref_expr, "length", comps[1].type());
1386+
exprt init_array_expr = member_exprt(deref_expr, "data", comps[2].type());
1387+
1388+
if(init_array_expr.type() != pointer_type(element_type))
1389+
init_array_expr =
1390+
typecast_exprt(init_array_expr, pointer_type(element_type));
1391+
1392+
// Nondeterministically initialise each element of the array
1393+
array_loop_init_code(
1394+
assignments,
1395+
init_array_expr,
1396+
length_expr,
1397+
element_type,
1398+
max_length_expr,
1399+
depth,
1400+
update_in_place,
1401+
location);
1402+
}
1403+
13371404
/// We nondet-initialize enums to be equal to one of the constants defined
13381405
/// for their type:
13391406
/// int i = nondet(int);

0 commit comments

Comments
 (0)