Skip to content

Commit 21439f4

Browse files
author
Daniel Kroening
authored
Merge pull request diffblue#1614 from polgreen/cegis_cbmc
Cegis cbmc
2 parents 91ef19e + 8a389f9 commit 21439f4

File tree

4 files changed

+195
-102
lines changed

4 files changed

+195
-102
lines changed

src/cbmc/bmc.cpp

Lines changed: 97 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ void bmct::do_unwind_module()
4545
// this is a hook for hw-cbmc
4646
}
4747

48+
/// Hook used by CEGIS to selectively freeze variables
49+
/// in the SAT solver after the SSA formula is added to the solver.
50+
/// Freezing variables is necessary to make use of incremental
51+
/// solving with MiniSat SimpSolver.
52+
/// Potentially a useful hook for other applications using
53+
/// incremental solving.
54+
void bmct::freeze_program_variables()
55+
{
56+
// this is a hook for cegis
57+
}
58+
4859
void bmct::error_trace()
4960
{
5061
status() << "Building error trace" << eom;
@@ -131,6 +142,8 @@ void bmct::do_conversion()
131142
forall_expr_list(it, bmc_constraints)
132143
prop_conv.set_to_true(*it);
133144
}
145+
// hook for cegis to freeze synthesis program vars
146+
freeze_program_variables();
134147
}
135148

136149
decision_proceduret::resultt
@@ -305,11 +318,10 @@ void bmct::show_program()
305318
}
306319
}
307320

308-
safety_checkert::resultt bmct::run(
309-
const goto_functionst &goto_functions)
321+
322+
void bmct::get_memory_model()
310323
{
311324
const std::string mm=options.get_option("mm");
312-
std::unique_ptr<memory_model_baset> memory_model;
313325

314326
if(mm.empty() || mm=="sc")
315327
memory_model=util_make_unique<memory_model_sct>(ns);
@@ -321,9 +333,13 @@ safety_checkert::resultt bmct::run(
321333
{
322334
error() << "Invalid memory model " << mm
323335
<< " -- use one of sc, tso, pso" << eom;
324-
return safety_checkert::resultt::ERROR;
336+
throw "invalid memory model";
325337
}
338+
}
326339

340+
void bmct::setup()
341+
{
342+
get_memory_model();
327343
symex.set_message_handler(get_message_handler());
328344
symex.options=options;
329345

@@ -337,11 +353,13 @@ safety_checkert::resultt bmct::run(
337353

338354
symex.last_source_location.make_nil();
339355

340-
try
341-
{
342-
// get unwinding info
343356
setup_unwind();
357+
}
344358

359+
safety_checkert::resultt bmct::execute(const goto_functionst &goto_functions)
360+
{
361+
try
362+
{
345363
// perform symbolic execution
346364
symex(goto_functions);
347365

@@ -351,77 +369,12 @@ safety_checkert::resultt bmct::run(
351369
memory_model->set_message_handler(get_message_handler());
352370
(*memory_model)(equation);
353371
}
354-
}
355-
356-
catch(const std::string &error_str)
357-
{
358-
messaget message(get_message_handler());
359-
message.error().source_location=symex.last_source_location;
360-
message.error() << error_str << messaget::eom;
361-
362-
return safety_checkert::resultt::ERROR;
363-
}
364-
365-
catch(const char *error_str)
366-
{
367-
messaget message(get_message_handler());
368-
message.error().source_location=symex.last_source_location;
369-
message.error() << error_str << messaget::eom;
370-
371-
return safety_checkert::resultt::ERROR;
372-
}
373-
374-
catch(const std::bad_alloc &)
375-
{
376-
error() << "Out of memory" << eom;
377-
return safety_checkert::resultt::ERROR;
378-
}
379372

380373
statistics() << "size of program expression: "
381374
<< equation.SSA_steps.size()
382375
<< " steps" << eom;
383376

384-
try
385-
{
386-
if(options.get_option("slice-by-trace")!="")
387-
{
388-
symex_slice_by_tracet symex_slice_by_trace(ns);
389-
390-
symex_slice_by_trace.slice_by_trace
391-
(options.get_option("slice-by-trace"), equation);
392-
}
393-
394-
if(equation.has_threads())
395-
{
396-
// we should build a thread-aware SSA slicer
397-
statistics() << "no slicing due to threads" << eom;
398-
}
399-
else
400-
{
401-
if(options.get_bool_option("slice-formula"))
402-
{
403-
slice(equation);
404-
statistics() << "slicing removed "
405-
<< equation.count_ignored_SSA_steps()
406-
<< " assignments" << eom;
407-
}
408-
else
409-
{
410-
if(options.get_list_option("cover").empty())
411-
{
412-
simple_slice(equation);
413-
statistics() << "simple slicing removed "
414-
<< equation.count_ignored_SSA_steps()
415-
<< " assignments" << eom;
416-
}
417-
}
418-
}
419-
420-
{
421-
statistics() << "Generated " << symex.total_vccs
422-
<< " VCC(s), " << symex.remaining_vccs
423-
<< " remaining after simplification" << eom;
424-
}
377+
slice();
425378

426379
// coverage report
427380
std::string cov_out=options.get_option("symex-coverage-report");
@@ -473,13 +426,19 @@ safety_checkert::resultt bmct::run(
473426

474427
catch(const std::string &error_str)
475428
{
476-
error() << error_str << eom;
429+
messaget message(get_message_handler());
430+
message.error().source_location=symex.last_source_location;
431+
message.error() << error_str << messaget::eom;
432+
477433
return safety_checkert::resultt::ERROR;
478434
}
479435

480436
catch(const char *error_str)
481437
{
482-
error() << error_str << eom;
438+
messaget message(get_message_handler());
439+
message.error().source_location=symex.last_source_location;
440+
message.error() << error_str << messaget::eom;
441+
483442
return safety_checkert::resultt::ERROR;
484443
}
485444

@@ -490,6 +449,56 @@ safety_checkert::resultt bmct::run(
490449
}
491450
}
492451

452+
void bmct::slice()
453+
{
454+
if(options.get_option("slice-by-trace")!="")
455+
{
456+
symex_slice_by_tracet symex_slice_by_trace(ns);
457+
458+
symex_slice_by_trace.slice_by_trace
459+
(options.get_option("slice-by-trace"),
460+
equation);
461+
}
462+
// any properties to check at all?
463+
if(equation.has_threads())
464+
{
465+
// we should build a thread-aware SSA slicer
466+
statistics() << "no slicing due to threads" << eom;
467+
}
468+
else
469+
{
470+
if(options.get_bool_option("slice-formula"))
471+
{
472+
::slice(equation);
473+
statistics() << "slicing removed "
474+
<< equation.count_ignored_SSA_steps()
475+
<< " assignments"<<eom;
476+
}
477+
else
478+
{
479+
if(options.get_list_option("cover").empty())
480+
{
481+
simple_slice(equation);
482+
statistics() << "simple slicing removed "
483+
<< equation.count_ignored_SSA_steps()
484+
<< " assignments"<<eom;
485+
}
486+
}
487+
}
488+
statistics() << "Generated "
489+
<< symex.total_vccs<<" VCC(s), "
490+
<< symex.remaining_vccs
491+
<< " remaining after simplification" << eom;
492+
}
493+
494+
safety_checkert::resultt bmct::run(
495+
const goto_functionst &goto_functions)
496+
{
497+
setup();
498+
499+
return execute(goto_functions);
500+
}
501+
493502
safety_checkert::resultt bmct::decide(
494503
const goto_functionst &goto_functions,
495504
prop_convt &prop_conv)
@@ -502,6 +511,19 @@ safety_checkert::resultt bmct::decide(
502511
return all_properties(goto_functions, prop_conv);
503512
}
504513

514+
void bmct::show(const goto_functionst &goto_functions)
515+
{
516+
if(options.get_bool_option("show-vcc"))
517+
{
518+
show_vcc();
519+
}
520+
521+
if(options.get_bool_option("program-only"))
522+
{
523+
show_program();
524+
}
525+
}
526+
505527
safety_checkert::resultt bmct::stop_on_fail(
506528
const goto_functionst &goto_functions,
507529
prop_convt &prop_conv)

src/cbmc/bmc.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Author: Daniel Kroening, [email protected]
2727

2828
#include <goto-symex/symex_target_equation.h>
2929
#include <goto-programs/safety_checker.h>
30+
#include <goto-symex/memory_model.h>
3031

3132
#include "symex_bmc.h"
3233

@@ -52,6 +53,8 @@ class bmct:public safety_checkert
5253
}
5354

5455
virtual resultt run(const goto_functionst &goto_functions);
56+
void setup();
57+
safety_checkert::resultt execute(const goto_functionst &);
5558
virtual ~bmct() { }
5659

5760
// additional stuff
@@ -73,7 +76,7 @@ class bmct:public safety_checkert
7376
symex_target_equationt equation;
7477
symex_bmct symex;
7578
prop_convt &prop_conv;
76-
79+
std::unique_ptr<memory_model_baset> memory_model;
7780
// use gui format
7881
ui_message_handlert::uit ui;
7982

@@ -89,6 +92,8 @@ class bmct:public safety_checkert
8992
virtual void do_unwind_module();
9093
void do_conversion();
9194

95+
virtual void freeze_program_variables();
96+
9297
virtual void show_vcc();
9398
virtual void show_vcc_plain(std::ostream &out);
9499
virtual void show_vcc_json(std::ostream &out);
@@ -108,6 +113,10 @@ class bmct:public safety_checkert
108113
resultt result,
109114
const goto_functionst &goto_functions);
110115

116+
void get_memory_model();
117+
void slice();
118+
void show(const goto_functionst &);
119+
111120
bool cover(
112121
const goto_functionst &goto_functions,
113122
const optionst::value_listt &criteria);

src/goto-symex/goto_symex.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,40 @@ class goto_symext
8080
const goto_functionst &goto_functions,
8181
const goto_programt &goto_program);
8282

83+
/// Symexes from the first instruction and the given state, terminating as
84+
/// soon as the last instruction is reached. This is useful to explicitly
85+
/// symex certain ranges of a program, e.g. in an incremental decision
86+
/// procedure.
87+
/// \param state Symex state to start with.
88+
/// \param goto_functions GOTO model to symex.
89+
/// \param first Entry point in form of a first instruction.
90+
/// \param limit Final instruction, which itself will not be symexed.
91+
virtual void operator()(
92+
statet &state,
93+
const goto_functionst &goto_functions,
94+
goto_programt::const_targett first,
95+
goto_programt::const_targett limit);
96+
97+
/// Initialise the symbolic execution and the given state with <code>pc</code>
98+
/// as entry point.
99+
/// \param state Symex state to initialise.
100+
/// \param goto_functions GOTO model to symex.
101+
/// \param pc first instruction to symex
102+
/// \param limit final instruction, which itself will not
103+
/// be symexed.
104+
void symex_entry_point(
105+
statet &state,
106+
const goto_functionst &goto_functions,
107+
goto_programt::const_targett pc,
108+
goto_programt::const_targett limit);
109+
110+
/// Invokes symex_step and verifies whether additional threads can be
111+
/// executed.
112+
/// \param state Current GOTO symex step.
113+
/// \param goto_functions GOTO model to symex.
114+
void symex_threaded_step(
115+
statet &state, const goto_functionst &goto_functions);
116+
83117
/** execute just one step */
84118
virtual void symex_step(
85119
const goto_functionst &goto_functions,

0 commit comments

Comments
 (0)