Skip to content

Commit e26d20e

Browse files
author
Daniel Kroening
authored
Merge pull request #207 from peterschrammel/trace-outputs
Test inputs and outputs for C and Java
2 parents 1218856 + cf0a82f commit e26d20e

File tree

5 files changed

+265
-20
lines changed

5 files changed

+265
-20
lines changed

src/ansi-c/ansi_c_entry_point.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ exprt::operandst build_function_environment(
6161
new_symbol.mode=ID_C;
6262
new_symbol.is_static_lifetime=false;
6363
new_symbol.name=identifier;
64+
new_symbol.base_name=base_name;
6465
new_symbol.type=p.type();
6566

6667
symbol_table.move(new_symbol);
@@ -93,6 +94,79 @@ exprt::operandst build_function_environment(
9394

9495
/*******************************************************************\
9596
97+
Function: record_function_outputs
98+
99+
Inputs:
100+
101+
Outputs:
102+
103+
Purpose:
104+
105+
\*******************************************************************/
106+
107+
void record_function_outputs(
108+
const symbolt &function,
109+
code_blockt &init_code,
110+
symbol_tablet &symbol_table)
111+
{
112+
const code_typet::parameterst &parameters=
113+
to_code_type(function.type).parameters();
114+
115+
exprt::operandst result;
116+
result.reserve(parameters.size()+1);
117+
118+
bool has_return_value=
119+
to_code_type(function.type).return_type()!=empty_typet();
120+
121+
if(has_return_value)
122+
{
123+
//record return value
124+
codet output(ID_output);
125+
output.operands().resize(2);
126+
127+
const symbolt &return_symbol=symbol_table.lookup("return'");
128+
129+
output.op0()=address_of_exprt(
130+
index_exprt(string_constantt(return_symbol.base_name),
131+
gen_zero(index_type())));
132+
output.op1()=return_symbol.symbol_expr();
133+
output.add_source_location()=
134+
function.value.operands().back().source_location();
135+
136+
init_code.move_to_operands(output);
137+
}
138+
139+
std::size_t i=0;
140+
141+
for(const auto & p : parameters)
142+
{
143+
irep_idt base_name=p.get_base_name();
144+
if(base_name.empty()) base_name="argument#"+i2string(i);
145+
irep_idt identifier=id2string(function.name)+
146+
"::"+id2string(base_name);
147+
148+
const symbolt &symbol = symbol_table.lookup(identifier);
149+
150+
if(symbol.type.id()==ID_pointer)
151+
{
152+
codet output(ID_output);
153+
output.operands().resize(2);
154+
155+
output.op0()=address_of_exprt(
156+
index_exprt(string_constantt(symbol.base_name),
157+
gen_zero(index_type())));
158+
output.op1()=symbol.symbol_expr();
159+
output.add_source_location()=p.source_location();
160+
161+
init_code.move_to_operands(output);
162+
}
163+
164+
i++;
165+
}
166+
}
167+
168+
/*******************************************************************\
169+
96170
Function: ansi_c_entry_point
97171
98172
Inputs:
@@ -203,6 +277,18 @@ bool ansi_c_entry_point(
203277
call_main.add_source_location()=symbol.location;
204278
call_main.function()=symbol.symbol_expr();
205279
call_main.function().add_source_location()=symbol.location;
280+
if(to_code_type(symbol.type).return_type()!=empty_typet())
281+
{
282+
auxiliary_symbolt return_symbol;
283+
return_symbol.mode=ID_C;
284+
return_symbol.is_static_lifetime=false;
285+
return_symbol.name="return'";
286+
return_symbol.base_name="return";
287+
return_symbol.type=to_code_type(symbol.type).return_type();
288+
289+
symbol_table.add(return_symbol);
290+
call_main.lhs()=return_symbol.symbol_expr();
291+
}
206292

207293
const code_typet::parameterst &parameters=
208294
to_code_type(symbol.type).parameters();
@@ -410,6 +496,10 @@ bool ansi_c_entry_point(
410496

411497
init_code.move_to_operands(call_main);
412498

499+
// TODO: add read/modified (recursively in call graph) globals as INPUT/OUTPUT
500+
501+
record_function_outputs(symbol, init_code, symbol_table);
502+
413503
// add the entry point symbol
414504
symbolt new_symbol;
415505

src/ansi-c/expr2c.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3542,6 +3542,9 @@ std::string expr2ct::convert_code(
35423542
if(statement==ID_input)
35433543
return convert_code_input(src, indent);
35443544

3545+
if(statement==ID_output)
3546+
return convert_code_output(src, indent);
3547+
35453548
if(statement==ID_assume)
35463549
return convert_code_assume(src, indent);
35473550

@@ -3889,6 +3892,38 @@ std::string expr2ct::convert_code_input(
38893892

38903893
/*******************************************************************\
38913894
3895+
Function: expr2ct::convert_code_output
3896+
3897+
Inputs:
3898+
3899+
Outputs:
3900+
3901+
Purpose:
3902+
3903+
\*******************************************************************/
3904+
3905+
std::string expr2ct::convert_code_output(
3906+
const codet &src,
3907+
unsigned indent)
3908+
{
3909+
std::string dest=indent_str(indent)+"OUTPUT(";
3910+
3911+
forall_operands(it, src)
3912+
{
3913+
unsigned p;
3914+
std::string arg_str=convert(*it, p);
3915+
3916+
if(it!=src.operands().begin()) dest+=", ";
3917+
dest+=arg_str;
3918+
}
3919+
3920+
dest+=");";
3921+
3922+
return dest;
3923+
}
3924+
3925+
/*******************************************************************\
3926+
38923927
Function: expr2ct::convert_code_array_set
38933928
38943929
Inputs:

src/ansi-c/expr2c_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class expr2ct
172172
std::string convert_code_printf(const codet &src, unsigned indent);
173173
std::string convert_code_fence(const codet &src, unsigned indent);
174174
std::string convert_code_input(const codet &src, unsigned indent);
175+
std::string convert_code_output(const codet &src, unsigned indent);
175176
std::string convert_code_array_set(const codet &src, unsigned indent);
176177
std::string convert_code_array_copy(const codet &src, unsigned indent);
177178

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ bool cbmc_parse_optionst::process_goto_program(
968968
return true;
969969
}
970970

971-
status() << "Instrumenting coverge goals" << eom;
971+
status() << "Instrumenting coverage goals" << eom;
972972
instrument_cover_goals(symbol_table, goto_functions, c);
973973
goto_functions.update();
974974
}

src/java_bytecode/java_entry_point.cpp

Lines changed: 138 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Author: Daniel Kroening, [email protected]
2222
#include <util/pointer_offset_size.h>
2323
#include <util/i2string.h>
2424
#include <util/prefix.h>
25+
#include <ansi-c/c_types.h>
26+
#include <ansi-c/string_constant.h>
2527

2628
#include <goto-programs/goto_functions.h>
2729

@@ -132,6 +134,128 @@ bool java_static_lifetime_init(
132134
return false;
133135
}
134136

137+
138+
/*******************************************************************\
139+
140+
Function: java_build_arguments
141+
142+
Inputs:
143+
144+
Outputs:
145+
146+
Purpose:
147+
148+
\*******************************************************************/
149+
150+
exprt::operandst java_build_arguments(
151+
const symbolt &function,
152+
code_blockt &init_code,
153+
symbol_tablet &symbol_table)
154+
{
155+
const code_typet::parameterst &parameters=
156+
to_code_type(function.type).parameters();
157+
158+
exprt::operandst main_arguments;
159+
main_arguments.resize(parameters.size());
160+
161+
for(std::size_t param_number=0;
162+
param_number<parameters.size();
163+
param_number++)
164+
{
165+
bool is_this=param_number==0 &&
166+
parameters[param_number].get_this();
167+
bool allow_null=config.main!="" && !is_this;
168+
169+
main_arguments[param_number]=
170+
object_factory(parameters[param_number].type(),
171+
init_code, allow_null, symbol_table);
172+
173+
const symbolt &p_symbol=
174+
symbol_table.lookup(parameters[param_number].get_identifier());
175+
176+
// record as an input
177+
codet input(ID_input);
178+
input.operands().resize(2);
179+
input.op0()=address_of_exprt(
180+
index_exprt(string_constantt(p_symbol.base_name),
181+
gen_zero(index_type())));
182+
input.op1()=main_arguments[param_number];
183+
input.add_source_location()=parameters[param_number].source_location();
184+
185+
init_code.move_to_operands(input);
186+
}
187+
188+
return main_arguments;
189+
}
190+
191+
/*******************************************************************\
192+
193+
Function: java_record_outputs
194+
195+
Inputs:
196+
197+
Outputs:
198+
199+
Purpose:
200+
201+
\*******************************************************************/
202+
203+
void java_record_outputs(
204+
const symbolt &function,
205+
const exprt::operandst &main_arguments,
206+
code_blockt &init_code,
207+
symbol_tablet &symbol_table)
208+
{
209+
const code_typet::parameterst &parameters=
210+
to_code_type(function.type).parameters();
211+
212+
exprt::operandst result;
213+
result.reserve(parameters.size()+1);
214+
215+
bool has_return_value=
216+
to_code_type(function.type).return_type()!=empty_typet();
217+
218+
if(has_return_value)
219+
{
220+
//record return value
221+
codet output(ID_output);
222+
output.operands().resize(2);
223+
224+
const symbolt &return_symbol=symbol_table.lookup("return'");
225+
226+
output.op0()=address_of_exprt(
227+
index_exprt(string_constantt(return_symbol.base_name),
228+
gen_zero(index_type())));
229+
output.op1()=return_symbol.symbol_expr();
230+
output.add_source_location()=
231+
function.value.operands().back().source_location();
232+
233+
init_code.move_to_operands(output);
234+
}
235+
236+
for(std::size_t param_number=0;
237+
param_number<parameters.size();
238+
param_number++)
239+
{
240+
const symbolt &p_symbol=
241+
symbol_table.lookup(parameters[param_number].get_identifier());
242+
243+
if(p_symbol.type.id()==ID_pointer)
244+
{
245+
// record as an output
246+
codet output(ID_output);
247+
output.operands().resize(2);
248+
output.op0()=address_of_exprt(
249+
index_exprt(string_constantt(p_symbol.base_name),
250+
gen_zero(index_type())));
251+
output.op1()=main_arguments[param_number];
252+
output.add_source_location()=parameters[param_number].source_location();
253+
254+
init_code.move_to_operands(output);
255+
}
256+
}
257+
}
258+
135259
/*******************************************************************\
136260
137261
Function: java_entry_point
@@ -287,8 +411,6 @@ bool java_entry_point(
287411
assert(!symbol.value.is_nil());
288412
assert(symbol.type.id()==ID_code);
289413

290-
const code_typet &code_type=to_code_type(symbol.type);
291-
292414
create_initialize(symbol_table);
293415

294416
if(java_static_lifetime_init(symbol_table, symbol.location, message_handler))
@@ -321,30 +443,27 @@ bool java_entry_point(
321443
code_function_callt call_main;
322444
call_main.add_source_location()=symbol.location;
323445
call_main.function()=symbol.symbol_expr();
324-
325-
const code_typet::parameterst &parameters=
326-
code_type.parameters();
327-
328-
exprt::operandst main_arguments;
329-
main_arguments.resize(parameters.size());
330-
331-
for(std::size_t param_number=0;
332-
param_number<parameters.size();
333-
param_number++)
446+
if(to_code_type(symbol.type).return_type()!=empty_typet())
334447
{
335-
bool is_this=param_number==0 &&
336-
parameters[param_number].get_this();
337-
bool allow_null=config.main!="" && !is_this;
338-
339-
main_arguments[param_number]=
340-
object_factory(parameters[param_number].type(),
341-
init_code, allow_null, symbol_table);
448+
auxiliary_symbolt return_symbol;
449+
return_symbol.mode=ID_C;
450+
return_symbol.is_static_lifetime=false;
451+
return_symbol.name="return'";
452+
return_symbol.base_name="return";
453+
return_symbol.type=to_code_type(symbol.type).return_type();
454+
455+
symbol_table.add(return_symbol);
456+
call_main.lhs()=return_symbol.symbol_expr();
342457
}
343458

459+
exprt::operandst main_arguments=
460+
java_build_arguments(symbol, init_code, symbol_table);
344461
call_main.arguments()=main_arguments;
345462

346463
init_code.move_to_operands(call_main);
347464

465+
java_record_outputs(symbol, main_arguments, init_code, symbol_table);
466+
348467
// add "main"
349468
symbolt new_symbol;
350469

0 commit comments

Comments
 (0)