Skip to content

Commit 9d232d4

Browse files
author
Daniel Kroening
authored
Merge pull request #1027 from thk123/refactor/gen-nondet-init-master
Refactor gen_nondet_init to master
2 parents 745a9b9 + e873e00 commit 9d232d4

File tree

2 files changed

+170
-99
lines changed

2 files changed

+170
-99
lines changed

src/goto-programs/class_hierarchy.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ Date: April 2016
1818

1919
#include "class_hierarchy.h"
2020

21+
/// Looks for all the struct types in the symbol table and construct a map from
22+
/// class names to a data structure that contains lists of parent and child
23+
/// classes for each struct type (ie class).
24+
/// \param symbol_table: The symbol table to analyze
2125
void class_hierarchyt::operator()(const symbol_tablet &symbol_table)
2226
{
2327
forall_symbols(it, symbol_table.symbols)

src/java_bytecode/java_object_factory.cpp

Lines changed: 166 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,22 @@ class java_object_factoryt
110110
bool create_dynamic_objects,
111111
bool override=false,
112112
const typet &override_type=empty_typet());
113+
114+
private:
115+
void gen_nondet_pointer_init(
116+
code_blockt &assignments,
117+
const exprt &expr,
118+
const irep_idt &class_identifier,
119+
bool create_dynamic_objects,
120+
const pointer_typet &pointer_type);
121+
122+
void gen_nondet_struct_init(
123+
code_blockt &assignments,
124+
const exprt &expr,
125+
bool is_sub,
126+
irep_idt class_identifier,
127+
bool create_dynamic_objects,
128+
const struct_typet &struct_type);
113129
};
114130

115131
/// \param assignments: The code block to add code to
@@ -250,6 +266,144 @@ void java_object_factoryt::gen_pointer_target_init(
250266
}
251267
}
252268

269+
/// Initialises a primitive or object tree rooted at `expr`, of type pointer. It
270+
/// allocates child objects as necessary and nondet-initialising their members,
271+
/// \param assignments - the code block we are building with
272+
/// initilisation code
273+
/// \param expr: lvalue expression to initialise
274+
/// \param class_identifier - the name of the class so we can identify
275+
/// special cases where a null pointer is not applicable.
276+
/// \param create_dynamic_objects: if true, use malloc to allocate objects;
277+
/// otherwise generate fresh static symbols.
278+
/// \param pointer_type - The type of the pointer we are initalising
279+
void java_object_factoryt::gen_nondet_pointer_init(
280+
code_blockt &assignments,
281+
const exprt &expr,
282+
const irep_idt &class_identifier,
283+
bool create_dynamic_objects,
284+
const pointer_typet &pointer_type)
285+
{
286+
const typet &subtype=ns.follow(pointer_type.subtype());
287+
288+
if(subtype.id()==ID_struct)
289+
{
290+
const struct_typet &struct_type=to_struct_type(subtype);
291+
const irep_idt struct_tag=struct_type.get_tag();
292+
// set to null if found in recursion set and not a sub-type
293+
if(recursion_set.find(struct_tag)!=recursion_set.end() &&
294+
struct_tag==class_identifier)
295+
{
296+
assignments.copy_to_operands(
297+
get_null_assignment(expr, pointer_type));
298+
return;
299+
}
300+
}
301+
302+
code_blockt non_null_inst;
303+
gen_pointer_target_init(
304+
non_null_inst,
305+
expr,
306+
subtype,
307+
create_dynamic_objects);
308+
309+
if(assume_non_null)
310+
{
311+
// Add the following code to assignments:
312+
// <expr> = <aoe>;
313+
assignments.append(non_null_inst);
314+
}
315+
else
316+
{
317+
// if(NONDET(_Bool)
318+
// {
319+
// <expr> = <null pointer>
320+
// }
321+
// else
322+
// {
323+
// <code from recursive call to gen_nondet_init() with
324+
// tmp$<temporary_counter>>
325+
// }
326+
auto set_null_inst=get_null_assignment(expr, pointer_type);
327+
328+
code_ifthenelset null_check;
329+
null_check.cond()=side_effect_expr_nondett(bool_typet());
330+
null_check.then_case()=set_null_inst;
331+
null_check.else_case()=non_null_inst;
332+
333+
assignments.add(null_check);
334+
}
335+
}
336+
337+
/// Initialises an object tree rooted at `expr`, allocating child objects as
338+
/// necessary and nondet-initialising their members.
339+
/// \param assignments: The code block to append the new
340+
/// instructions to
341+
/// \param expr: pointer-typed lvalue expression to initialise
342+
/// \param is_sub: If true, `expr` is a substructure of a larger object, which
343+
/// in Java necessarily means a base class. not match *expr (for example, expr
344+
/// might be void*)
345+
/// \param class_identifier: clsid to initialise @java.lang.Object.
346+
/// @class_identifier
347+
/// \param create_dynamic_objects: if true, use malloc to allocate objects;
348+
/// otherwise generate fresh static symbols.
349+
/// \param struct_type - The type of the struct we are initalising
350+
void java_object_factoryt::gen_nondet_struct_init(
351+
code_blockt &assignments,
352+
const exprt &expr,
353+
bool is_sub,
354+
irep_idt class_identifier,
355+
bool create_dynamic_objects,
356+
const struct_typet &struct_type)
357+
{
358+
typedef struct_typet::componentst componentst;
359+
360+
const irep_idt struct_tag=struct_type.get_tag();
361+
362+
const componentst &components=struct_type.components();
363+
364+
if(!is_sub)
365+
class_identifier=struct_tag;
366+
367+
recursion_set.insert(struct_tag);
368+
369+
for(const auto &component : components)
370+
{
371+
const typet &component_type=component.type();
372+
irep_idt name=component.get_name();
373+
374+
member_exprt me(expr, name, component_type);
375+
376+
if(name=="@class_identifier")
377+
{
378+
irep_idt qualified_clsid="java::"+as_string(class_identifier);
379+
constant_exprt ci(qualified_clsid, string_typet());
380+
code_assignt code(me, ci);
381+
code.add_source_location()=loc;
382+
assignments.copy_to_operands(code);
383+
}
384+
else if(name=="@lock")
385+
{
386+
code_assignt code(me, from_integer(0, me.type()));
387+
code.add_source_location()=loc;
388+
assignments.copy_to_operands(code);
389+
}
390+
else
391+
{
392+
INVARIANT(!name.empty(), "Each component of a struct must have a name");
393+
394+
bool _is_sub=name[0]=='@';
395+
396+
gen_nondet_init(
397+
assignments,
398+
me,
399+
_is_sub,
400+
class_identifier,
401+
create_dynamic_objects);
402+
}
403+
}
404+
recursion_set.erase(struct_tag);
405+
}
406+
253407
/// Creates a nondet for expr, including calling itself recursively to make
254408
/// appropriate symbols to point to if expr is a pointer or struct
255409
/// \param expr: The expression which we are generating a non-determinate value
@@ -277,110 +431,23 @@ void java_object_factoryt::gen_nondet_init(
277431
{
278432
// dereferenced type
279433
const pointer_typet &pointer_type=to_pointer_type(type);
280-
const typet &subtype=ns.follow(pointer_type.subtype());
281-
282-
if(subtype.id()==ID_struct)
283-
{
284-
const struct_typet &struct_type=to_struct_type(subtype);
285-
const irep_idt struct_tag=struct_type.get_tag();
286-
// set to null if found in recursion set and not a sub-type
287-
if(recursion_set.find(struct_tag)!=recursion_set.end() &&
288-
struct_tag==class_identifier)
289-
{
290-
assignments.copy_to_operands(
291-
get_null_assignment(expr, pointer_type));
292-
return;
293-
}
294-
}
295-
296-
code_blockt non_null_inst;
297-
gen_pointer_target_init(
298-
non_null_inst,
434+
gen_nondet_pointer_init(
435+
assignments,
299436
expr,
300-
subtype,
301-
create_dynamic_objects);
302-
303-
if(assume_non_null)
304-
{
305-
// Add the following code to assignments:
306-
// <expr> = <aoe>;
307-
assignments.append(non_null_inst);
308-
}
309-
else
310-
{
311-
// Add the following code to assignments:
312-
// IF !NONDET(_Bool) THEN GOTO <label1>
313-
// <expr> = <null pointer>
314-
// GOTO <label2>
315-
// <label1>: <expr> = &tmp$<temporary_counter>;
316-
// <code from recursive call to gen_nondet_init() with
317-
// tmp$<temporary_counter>>
318-
// And the next line is labelled label2
319-
auto set_null_inst=get_null_assignment(expr, pointer_type);
320-
321-
code_ifthenelset null_check;
322-
null_check.cond()=side_effect_expr_nondett(bool_typet());
323-
null_check.then_case()=set_null_inst;
324-
null_check.else_case()=non_null_inst;
325-
326-
assignments.add(null_check);
327-
}
437+
class_identifier,
438+
create_dynamic_objects,
439+
pointer_type);
328440
}
329441
else if(type.id()==ID_struct)
330442
{
331-
typedef struct_typet::componentst componentst;
332-
333443
const struct_typet &struct_type=to_struct_type(type);
334-
const irep_idt struct_tag=struct_type.get_tag();
335-
336-
const componentst &components=struct_type.components();
337-
338-
if(!is_sub)
339-
class_identifier=struct_tag;
340-
341-
recursion_set.insert(struct_tag);
342-
assert(!recursion_set.empty());
343-
344-
for(const auto &component : components)
345-
{
346-
const typet &component_type=component.type();
347-
irep_idt name=component.get_name();
348-
349-
member_exprt me(expr, name, component_type);
350-
351-
if(name=="@class_identifier")
352-
{
353-
irep_idt qualified_clsid="java::"+as_string(class_identifier);
354-
constant_exprt ci(qualified_clsid, string_typet());
355-
code_assignt code(me, ci);
356-
code.add_source_location()=loc;
357-
assignments.copy_to_operands(code);
358-
}
359-
else if(name=="@lock")
360-
{
361-
code_assignt code(me, from_integer(0, me.type()));
362-
code.add_source_location()=loc;
363-
assignments.copy_to_operands(code);
364-
}
365-
else
366-
{
367-
assert(!name.empty());
368-
369-
bool _is_sub=name[0]=='@';
370-
#if 0
371-
irep_idt _class_identifier=
372-
_is_sub?(class_identifier.empty()?struct_tag:class_identifier):"";
373-
#endif
374-
375-
gen_nondet_init(
376-
assignments,
377-
me,
378-
_is_sub,
379-
class_identifier,
380-
create_dynamic_objects);
381-
}
382-
}
383-
recursion_set.erase(struct_tag);
444+
gen_nondet_struct_init(
445+
assignments,
446+
expr,
447+
is_sub,
448+
class_identifier,
449+
create_dynamic_objects,
450+
struct_type);
384451
}
385452
else
386453
{

0 commit comments

Comments
 (0)