Skip to content

Commit cf9c082

Browse files
authored
Merge pull request diffblue#162 from viktormalik/dynobj-management
Improve management of dynamic objects
2 parents 33e3260 + 9106d17 commit cf9c082

37 files changed

+880
-831
lines changed

src/2ls/2ls_parse_options.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Author: Daniel Kroening, Peter Schrammel
5555
#include "graphml_witness_ext.h"
5656
#include <solver/summary_db.h>
5757
#include <ssa/dynobj_instance_analysis.h>
58+
#include <ssa/dynamic_objects.h>
5859

5960
#include "2ls_parse_options.h"
6061
#include "summary_checker_ai.h"
@@ -76,8 +77,7 @@ twols_parse_optionst::twols_parse_optionst(int argc, const char **argv):
7677
messaget(ui_message_handler),
7778
ui_message_handler(cmdline, "2LS " TWOLS_VERSION),
7879
recursion_detected(false),
79-
threads_detected(false),
80-
dynamic_memory_detected(false)
80+
threads_detected(false)
8181
{
8282
}
8383

@@ -408,7 +408,7 @@ int twols_parse_optionst::doit()
408408
if(get_goto_program(options))
409409
return 6;
410410

411-
if(cmdline.isset("heap") && dynamic_memory_detected)
411+
if(cmdline.isset("heap") && dynamic_objects->have_objects())
412412
{
413413
// Only use sympath domain if dynamic memory is used
414414
options.set_option("sympath", true);
@@ -430,6 +430,7 @@ int twols_parse_optionst::doit()
430430
irep_idt function=cmdline.get_value("function");
431431
show_ssa(
432432
goto_model,
433+
*dynamic_objects,
433434
options,
434435
function,
435436
simplify,
@@ -441,15 +442,26 @@ int twols_parse_optionst::doit()
441442
if(cmdline.isset("show-defs"))
442443
{
443444
irep_idt function=cmdline.get_value("function");
444-
show_defs(goto_model, function, options, std::cout, ui_message_handler);
445+
show_defs(
446+
goto_model,
447+
function,
448+
*dynamic_objects,
449+
options,
450+
std::cout,
451+
ui_message_handler);
445452
return 7;
446453
}
447454

448455
if(cmdline.isset("show-assignments"))
449456
{
450457
irep_idt function=cmdline.get_value("function");
451458
show_assignments(
452-
goto_model, function, options, std::cout, ui_message_handler);
459+
goto_model,
460+
function,
461+
*dynamic_objects,
462+
options,
463+
std::cout,
464+
ui_message_handler);
453465
return 7;
454466
}
455467

@@ -556,7 +568,7 @@ int twols_parse_optionst::doit()
556568
options.get_bool_option("incremental-bmc") ||
557569
options.get_unsigned_int_option("unwind")) &&
558570
!options.get_bool_option("nontermination") &&
559-
dynamic_memory_detected)
571+
dynamic_objects->have_objects())
560572
{
561573
status() << "Using GOTO unwinder due to presence of dynamic memory" << eom;
562574
options.set_option("unwind-goto", true);
@@ -566,7 +578,7 @@ int twols_parse_optionst::doit()
566578
if(options.get_bool_option("competition-mode") &&
567579
(options.get_bool_option("termination") ||
568580
options.get_bool_option("nontermination")) &&
569-
dynamic_memory_detected)
581+
dynamic_objects->have_objects())
570582
{
571583
error() << "Termination analysis does not support "
572584
<< "dynamic memory allocation" << eom;
@@ -580,18 +592,18 @@ int twols_parse_optionst::doit()
580592
if(!options.get_bool_option("k-induction") &&
581593
!options.get_bool_option("incremental-bmc"))
582594
checker=std::unique_ptr<summary_checker_baset>(
583-
new summary_checker_ait(options, goto_model));
595+
new summary_checker_ait(options, goto_model, *dynamic_objects));
584596
if(options.get_bool_option("k-induction") &&
585597
!options.get_bool_option("incremental-bmc"))
586598
checker=std::unique_ptr<summary_checker_baset>(
587-
new summary_checker_kindt(options, goto_model));
599+
new summary_checker_kindt(options, goto_model, *dynamic_objects));
588600
if(!options.get_bool_option("k-induction") &&
589601
options.get_bool_option("incremental-bmc"))
590602
checker=std::unique_ptr<summary_checker_baset>(
591-
new summary_checker_bmct(options, goto_model));
603+
new summary_checker_bmct(options, goto_model, *dynamic_objects));
592604
if(options.get_bool_option("nontermination"))
593605
checker=std::unique_ptr<summary_checker_baset>(
594-
new summary_checker_nontermt(options, goto_model));
606+
new summary_checker_nontermt(options, goto_model, *dynamic_objects));
595607

596608
checker->set_message_handler(get_message_handler());
597609
checker->simplify=!cmdline.isset("no-simplify");
@@ -613,7 +625,7 @@ int twols_parse_optionst::doit()
613625

614626
if(out_file=="-")
615627
{
616-
horn_encoding(goto_model, options, std::cout);
628+
horn_encoding(goto_model, *dynamic_objects, options, std::cout);
617629
}
618630
else
619631
{
@@ -630,7 +642,7 @@ int twols_parse_optionst::doit()
630642
return 1;
631643
}
632644

633-
horn_encoding(goto_model, options, out);
645+
horn_encoding(goto_model, *dynamic_objects, options, out);
634646
}
635647

636648
return 0;
@@ -1110,8 +1122,8 @@ bool twols_parse_optionst::process_goto_program(
11101122
goto_model.goto_functions.compute_loop_numbers();
11111123

11121124
// Replace malloc
1113-
dynamic_memory_detected=replace_malloc(
1114-
goto_model, "", options.get_bool_option("pointer-check"));
1125+
dynamic_objects=util_make_unique<dynamic_objectst>(goto_model);
1126+
dynamic_objects->replace_malloc(options.get_bool_option("pointer-check"));
11151127

11161128
// Allow recording of mallocs and memory leaks
11171129
if(options.get_bool_option("pointer-check"))
@@ -1136,7 +1148,7 @@ bool twols_parse_optionst::process_goto_program(
11361148
inline_main(goto_model);
11371149
}
11381150

1139-
auto dynobj_instances=split_dynamic_objects(goto_model, options);
1151+
dynamic_objects->generate_instances(options);
11401152

11411153
if(!cmdline.isset("independent-properties"))
11421154
{

src/2ls/2ls_parse_options.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Author: Daniel Kroening, Peter Schrammel
1717
#include <util/replace_symbol.h>
1818

1919
#include <analyses/goto_check.h>
20-
#include <ssa/dynobj_instance_analysis.h>
20+
#include <ssa/dynamic_objects.h>
2121

2222
class goto_modelt;
2323
class optionst;
@@ -83,7 +83,8 @@ class twols_parse_optionst:
8383
ui_message_handlert ui_message_handler;
8484
bool recursion_detected;
8585
bool threads_detected;
86-
bool dynamic_memory_detected;
86+
std::unique_ptr<dynamic_objectst> dynamic_objects;
87+
8788
virtual void register_languages();
8889

8990
void get_command_line_options(optionst &options);
@@ -180,18 +181,6 @@ class twols_parse_optionst:
180181
void add_dynamic_object_rec(exprt &expr, symbol_tablet &symbol_table);
181182
void split_same_symbolic_object_assignments(goto_modelt &goto_model);
182183
void remove_dead_goto(goto_modelt &goto_model);
183-
void compute_dynobj_instances(
184-
const goto_programt &goto_program,
185-
const dynobj_instance_analysist &analysis,
186-
std::map<symbol_exprt, size_t> &instance_counts,
187-
const namespacet &ns);
188-
void create_dynobj_instances(
189-
goto_programt &goto_program,
190-
const std::map<symbol_exprt, size_t> &instance_counts,
191-
symbol_tablet &symbol_table);
192-
std::map<symbol_exprt, size_t> split_dynamic_objects(
193-
goto_modelt &goto_model,
194-
const optionst &options);
195184
void limit_array_bounds(goto_modelt &goto_model);
196185
void memory_assert_info(goto_modelt &goto_model);
197186
void handle_freed_ptr_compare(goto_modelt &goto_model);

src/2ls/horn_encoding.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ class horn_encodingt
2222
public:
2323
horn_encodingt(
2424
const goto_modelt &_goto_model,
25+
dynamic_objectst &_dynamic_objects,
2526
const optionst &_options,
2627
std::ostream &_out):
2728
goto_functions(_goto_model.goto_functions),
2829
symbol_table(_goto_model.symbol_table),
2930
ns(_goto_model.symbol_table),
31+
dynamic_objects(_dynamic_objects),
3032
options(_options),
3133
out(_out),
3234
smt2_conv(ns, "", "Horn-clause encoding", "", smt2_convt::solvert::Z3, _out)
@@ -39,6 +41,7 @@ class horn_encodingt
3941
const goto_functionst &goto_functions;
4042
const symbol_tablet &symbol_table;
4143
const namespacet ns;
44+
dynamic_objectst &dynamic_objects;
4245
const optionst &options;
4346
std::ostream &out;
4447

@@ -66,7 +69,13 @@ void horn_encodingt::translate(
6669
";\n";
6770

6871
// compute SSA
69-
local_SSAt local_SSA(function_id, function, symbol_table, options, "");
72+
local_SSAt local_SSA(
73+
function_id,
74+
function,
75+
symbol_table,
76+
dynamic_objects,
77+
options,
78+
"");
7079

7180
const goto_programt &body=function.body;
7281

@@ -214,8 +223,9 @@ void horn_encodingt::translate(
214223

215224
void horn_encoding(
216225
const goto_modelt &goto_model,
226+
dynamic_objectst &dynamic_objects,
217227
const optionst &options,
218228
std::ostream &out)
219229
{
220-
horn_encodingt(goto_model, options, out)();
230+
horn_encodingt(goto_model, dynamic_objects, options, out)();
221231
}

src/2ls/horn_encoding.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Module: Horn-clause Encoding
1717
#include <goto-programs/goto_model.h>
1818

1919
void horn_encoding(
20-
const goto_modelt &,
20+
const goto_modelt &goto_model,
21+
dynamic_objectst &dynamic_objects,
2122
const optionst &options,
2223
std::ostream &out);
2324

src/2ls/preprocessing_util.cpp

Lines changed: 0 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -518,153 +518,6 @@ void twols_parse_optionst::remove_dead_goto(goto_modelt &goto_model)
518518
}
519519
}
520520

521-
/// For each allocation site, compute the number of objects that must be used to
522-
/// soundly represent all objects allocated at the given site.
523-
void twols_parse_optionst::compute_dynobj_instances(
524-
const goto_programt &goto_program,
525-
const dynobj_instance_analysist &analysis,
526-
std::map<symbol_exprt, size_t> &instance_counts,
527-
const namespacet &ns)
528-
{
529-
forall_goto_program_instructions(it, goto_program)
530-
{
531-
auto &analysis_value=analysis[it];
532-
for(auto &obj : analysis_value.live_pointers)
533-
{
534-
auto must_alias=analysis_value.must_alias_relations.find(obj.first);
535-
if(must_alias==analysis_value.must_alias_relations.end())
536-
continue;
537-
538-
std::set<size_t> alias_classes;
539-
for(auto &expr : obj.second)
540-
{
541-
size_t n;
542-
const auto number=must_alias->second.data.get_number(expr);
543-
if(!number)
544-
continue;
545-
n=*number;
546-
alias_classes.insert(must_alias->second.data.find_number(n));
547-
}
548-
549-
if(instance_counts.find(obj.first)==instance_counts.end() ||
550-
instance_counts.at(obj.first)<alias_classes.size())
551-
{
552-
instance_counts[obj.first]=alias_classes.size();
553-
}
554-
}
555-
}
556-
}
557-
558-
/// For each allocation site, split the allocated abstract dynamic object into
559-
/// multiple in order to preserve soundness of the analysis.
560-
void twols_parse_optionst::create_dynobj_instances(
561-
goto_programt &goto_program,
562-
const std::map<symbol_exprt, size_t> &instance_counts,
563-
symbol_tablet &symbol_table)
564-
{
565-
Forall_goto_program_instructions(it, goto_program)
566-
{
567-
if(it->is_assign())
568-
{
569-
auto &assign=to_code_assign(it->code_nonconst());
570-
if(assign.rhs().get_bool("#malloc_result"))
571-
{
572-
exprt &rhs=assign.rhs();
573-
exprt &abstract_obj=rhs.id()==ID_if ? to_if_expr(rhs).false_case()
574-
: rhs;
575-
exprt &address=abstract_obj.id()==ID_typecast ?
576-
to_typecast_expr(abstract_obj).op() : abstract_obj;
577-
if(address.id()!=ID_address_of)
578-
continue;
579-
exprt &obj=to_address_of_expr(address).object();
580-
if(obj.id()!=ID_symbol)
581-
continue;
582-
583-
if(obj.get_bool("#concrete"))
584-
continue;
585-
586-
if(instance_counts.find(to_symbol_expr(obj))==instance_counts.end())
587-
continue;
588-
589-
size_t count=instance_counts.at(to_symbol_expr(obj));
590-
if(count<=1)
591-
continue;
592-
593-
symbolt obj_symbol=
594-
symbol_table.get_writeable_ref(to_symbol_expr(obj).get_identifier());
595-
596-
const std::string name=id2string(obj_symbol.name);
597-
const std::string base_name=id2string(obj_symbol.base_name);
598-
std::string suffix="$"+std::to_string(0);
599-
600-
obj_symbol.name=name+suffix;
601-
obj_symbol.base_name=base_name+suffix;
602-
symbol_table.add(obj_symbol);
603-
604-
exprt new_rhs=address_of_exprt(obj_symbol.symbol_expr());
605-
if(abstract_obj.id()==ID_typecast)
606-
new_rhs=typecast_exprt(new_rhs, rhs.type());
607-
new_rhs.set("#malloc_result", true);
608-
609-
for(size_t i=1; i<count; ++i)
610-
{
611-
symbolt nondet;
612-
nondet.type=bool_typet();
613-
nondet.name="$guard#os"+std::to_string(it->location_number)+"#"+
614-
std::to_string(i);
615-
nondet.base_name=nondet.name;
616-
nondet.pretty_name=nondet.name;
617-
symbol_table.add(nondet);
618-
619-
const exprt nondet_bool_expr =
620-
side_effect_expr_nondett(bool_typet(), it->source_location);
621-
goto_program.insert_before(
622-
it,
623-
goto_programt::make_assignment(
624-
code_assignt(nondet.symbol_expr(), nondet_bool_expr),
625-
it->source_location));
626-
627-
suffix="$"+std::to_string(i);
628-
obj_symbol.name=name+suffix;
629-
obj_symbol.base_name=base_name+suffix;
630-
631-
exprt new_obj=address_of_exprt(obj_symbol.symbol_expr());
632-
if(abstract_obj.id()==ID_typecast)
633-
new_obj=typecast_exprt(new_obj, rhs.type());
634-
new_rhs=if_exprt(
635-
nondet.symbol_expr(), new_obj, new_rhs);
636-
new_rhs.set("#malloc_result", true);
637-
}
638-
639-
abstract_obj=new_rhs;
640-
abstract_obj.set("#malloc_result", true);
641-
}
642-
}
643-
}
644-
}
645-
646-
std::map<symbol_exprt, size_t> twols_parse_optionst::split_dynamic_objects(
647-
goto_modelt &goto_model,
648-
const optionst &options)
649-
{
650-
std::map<symbol_exprt, size_t> dynobj_instances;
651-
for(auto &f_it : goto_model.goto_functions.function_map)
652-
{
653-
if(!f_it.second.body_available())
654-
continue;
655-
namespacet ns(goto_model.symbol_table);
656-
ssa_value_ait value_analysis(f_it.first, f_it.second, ns, options);
657-
dynobj_instance_analysist do_inst(
658-
f_it.first, f_it.second, ns, options, value_analysis);
659-
660-
compute_dynobj_instances(
661-
f_it.second.body, do_inst, dynobj_instances, ns);
662-
create_dynobj_instances(
663-
f_it.second.body, dynobj_instances, goto_model.symbol_table);
664-
}
665-
return dynobj_instances;
666-
}
667-
668521
/// Assert size of static arrays to be max 50000.
669522
void twols_parse_optionst::limit_array_bounds(goto_modelt &goto_model)
670523
{

0 commit comments

Comments
 (0)