Skip to content

Commit 5624b15

Browse files
author
Daniel Kroening
committed
instrumentation for preconditions
1 parent 54e80da commit 5624b15

File tree

5 files changed

+173
-0
lines changed

5 files changed

+173
-0
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Author: Daniel Kroening, kroening@kroening.com
2727

2828
#include <goto-programs/convert_nondet.h>
2929
#include <goto-programs/initialize_goto_model.h>
30+
#include <goto-programs/instrument_preconditions.h>
3031
#include <goto-programs/goto_convert_functions.h>
3132
#include <goto-programs/goto_inline.h>
3233
#include <goto-programs/link_to_library.h>
@@ -780,6 +781,9 @@ bool cbmc_parse_optionst::process_goto_program(
780781

781782
mm_io(goto_model);
782783

784+
// instrument library preconditions
785+
instrument_preconditions(goto_model);
786+
783787
// do partial inlining
784788
status() << "Partial Inlining" << eom;
785789
goto_partial_inline(goto_model, get_message_handler());

src/goto-programs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ SRC = basic_blocks.cpp \
2323
goto_program_template.cpp \
2424
goto_trace.cpp \
2525
graphml_witness.cpp \
26+
instrument_preconditions.cpp \
2627
interpreter.cpp \
2728
interpreter_evaluate.cpp \
2829
json_goto_trace.cpp \
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*******************************************************************\
2+
3+
Module: Move preconditions of a function
4+
to the call-site of the function
5+
6+
Author: Daniel Kroening
7+
8+
Date: September 2017
9+
10+
\*******************************************************************/
11+
12+
#include "instrument_preconditions.h"
13+
14+
#include <util/replace_symbol.h>
15+
16+
std::vector<goto_programt::const_targett> get_preconditions(
17+
const symbol_exprt &function,
18+
const goto_functionst &goto_functions)
19+
{
20+
const irep_idt &identifier=function.get_identifier();
21+
22+
auto f_it=goto_functions.function_map.find(identifier);
23+
if(f_it==goto_functions.function_map.end())
24+
return {};
25+
26+
const auto &body=f_it->second.body;
27+
28+
std::vector<goto_programt::const_targett> result;
29+
30+
for(auto i_it=body.instructions.begin();
31+
i_it!=body.instructions.end();
32+
i_it++)
33+
{
34+
if(i_it->is_location() ||
35+
i_it->is_skip())
36+
continue; // ignore
37+
38+
if(i_it->is_assert() &&
39+
i_it->source_location.get_property_class()==ID_precondition)
40+
result.push_back(i_it);
41+
else
42+
break; // preconditions must be at the front
43+
}
44+
45+
return result;
46+
}
47+
48+
void remove_preconditions(goto_programt &goto_program)
49+
{
50+
for(auto &instruction : goto_program.instructions)
51+
{
52+
if(instruction.is_location() ||
53+
instruction.is_skip())
54+
continue; // ignore
55+
56+
if(instruction.is_assert() &&
57+
instruction.source_location.get_property_class()==ID_precondition)
58+
instruction.type=LOCATION;
59+
else
60+
break; // preconditions must be at the front
61+
}
62+
}
63+
64+
replace_symbolt actuals_replace_map(
65+
const code_function_callt &call,
66+
const namespacet &ns)
67+
{
68+
PRECONDITION(call.function().id()==ID_symbol);
69+
const symbolt &s=ns.lookup(to_symbol_expr(call.function()));
70+
const auto &code_type=to_code_type(s.type);
71+
const auto &parameters=code_type.parameters();
72+
const auto &arguments=call.arguments();
73+
74+
replace_symbolt result;
75+
std::size_t count=0;
76+
for(const auto &p : parameters)
77+
{
78+
if(p.get_identifier()!=irep_idt() &&
79+
arguments.size()>count)
80+
{
81+
exprt a=arguments[count];
82+
if(a.type()!=p.type())
83+
a=typecast_exprt(a, p.type());
84+
symbol_exprt s(p.get_identifier(), p.type());
85+
result.insert(s, a);
86+
}
87+
count++;
88+
}
89+
90+
return result;
91+
}
92+
93+
void instrument_preconditions(
94+
const goto_modelt &goto_model,
95+
goto_programt &goto_program)
96+
{
97+
const namespacet ns(goto_model.symbol_table);
98+
99+
for(auto it=goto_program.instructions.begin();
100+
it!=goto_program.instructions.end();
101+
it++)
102+
{
103+
if(it->is_function_call())
104+
{
105+
// does the function we call have preconditions?
106+
const auto &call=to_code_function_call(it->code);
107+
108+
if(call.function().id()==ID_symbol)
109+
{
110+
auto preconditions=
111+
get_preconditions(to_symbol_expr(call.function()),
112+
goto_model.goto_functions);
113+
114+
source_locationt source_location=it->source_location;
115+
irep_idt function=it->function;
116+
117+
replace_symbolt r=actuals_replace_map(call, ns);
118+
119+
// add before the call, with location of the call
120+
for(const auto &p : preconditions)
121+
{
122+
goto_program.insert_before_swap(it);
123+
exprt instance=p->guard;
124+
r(instance);
125+
it->make_assertion(instance);
126+
it->function=function;
127+
it->source_location=source_location;
128+
it->source_location.set_property_class(ID_precondition_instance);
129+
it->source_location.set_comment(p->source_location.get_comment());
130+
it++;
131+
}
132+
}
133+
}
134+
}
135+
}
136+
137+
void instrument_preconditions(goto_modelt &goto_model)
138+
{
139+
// add at call site
140+
for(auto &f_it : goto_model.goto_functions.function_map)
141+
instrument_preconditions(
142+
goto_model,
143+
f_it.second.body);
144+
145+
// now remove the preconditions
146+
for(auto &f_it : goto_model.goto_functions.function_map)
147+
remove_preconditions(f_it.second.body);
148+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*******************************************************************\
2+
3+
Module: Move preconditions of a function
4+
to the call-site of the function
5+
6+
Author: Daniel Kroening
7+
8+
Date: September 2017
9+
10+
\*******************************************************************/
11+
12+
#ifndef CPROVER_GOTO_PROGRAMS_INSTRUMENT_PRECONDITIONS_H
13+
#define CPROVER_GOTO_PROGRAMS_INSTRUMENT_PRECONDITIONS_H
14+
15+
#include <goto-programs/goto_model.h>
16+
17+
void instrument_preconditions(goto_modelt &);
18+
19+
#endif // CPROVER_GOTO_PROGRAMS_INSTRUMENT_PRECONDITIONS_H

src/util/irep_ids.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ IREP_ID_ONE(assume)
9191
IREP_ID_ONE(assert)
9292
IREP_ID_ONE(assertion)
9393
IREP_ID_ONE(precondition)
94+
IREP_ID_ONE(precondition_instance)
9495
IREP_ID_ONE(goto)
9596
IREP_ID_ONE(gcc_computed_goto)
9697
IREP_ID_ONE(ifthenelse)

0 commit comments

Comments
 (0)