Skip to content

Commit e8e1677

Browse files
committed
dump-c: output a generated environment via --harness
dump-c previously would not print __CPROVER__start code as this is deemed tool-internal. With increasing support for test-harness construction, the harness code may be of interest to users, who may wish to tweak and use re-use it.
1 parent 4c94e7c commit e8e1677

File tree

9 files changed

+136
-9
lines changed

9 files changed

+136
-9
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* GOTO-INSTRUMENT: New option --remove-function-body
1111
* GOTO-INSTRUMENT: New option --use-all-headers, changed --use-system-headers to
1212
--no-system-headers
13+
* GOTO-INSTRUMENT: dump-c can output the generated environment via --harness
1314

1415

1516
5.7
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char* argv[])
4+
{
5+
assert(argc<2 || argv[1]!=0);
6+
7+
return 0;
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--model-argc-argv 3 --dump-c --harness
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
Adding up to 3 command line arguments
7+
--
8+
^warning: ignoring

src/clobber/clobber_parse_options.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ int clobber_parse_optionst::doit()
147147
if(!out)
148148
throw std::string("failed to create file simulator.c");
149149

150-
dump_c(goto_functions, true, false, ns, out);
150+
dump_c(goto_functions, true, false, false, ns, out);
151151

152152
status() << "instrumentation complete; compile and execute simulator.c"
153153
<< eom;

src/goto-instrument/dump_c.cpp

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Author: Daniel Kroening, [email protected]
2121
#include <util/find_symbols.h>
2222
#include <util/base_type.h>
2323
#include <util/cprover_prefix.h>
24+
#include <util/replace_symbol.h>
2425

2526
#include <ansi-c/ansi_c_language.h>
2627
#include <cpp/cpp_language.h>
@@ -149,7 +150,8 @@ void dump_ct::operator()(std::ostream &os)
149150
// we don't want to dump in full all definitions; in particular
150151
// do not dump anonymous types that are defined in system headers
151152
if((!tag_added || symbol.is_type) &&
152-
system_symbols.is_symbol_internal_symbol(symbol, system_headers))
153+
system_symbols.is_symbol_internal_symbol(symbol, system_headers) &&
154+
symbol.name!=goto_functions.entry_point())
153155
continue;
154156

155157
bool inserted=symbols_sorted.insert(name_str).second;
@@ -198,7 +200,8 @@ void dump_ct::operator()(std::ostream &os)
198200
goto_functionst::function_mapt::const_iterator func_entry=
199201
goto_functions.function_map.find(symbol.name);
200202

201-
if(func_entry!=goto_functions.function_map.end() &&
203+
if(!harness &&
204+
func_entry!=goto_functions.function_map.end() &&
202205
func_entry->second.body_available() &&
203206
(symbol.name==ID_main ||
204207
(!config.main.empty() && symbol.name==config.main)))
@@ -946,6 +949,63 @@ void dump_ct::convert_global_variable(
946949
}
947950
}
948951

952+
/// Replace CPROVER internal symbols in b by printable values and generate
953+
/// necessary declarations.
954+
/// \param b: Code block to be cleaned
955+
void dump_ct::cleanup_harness(code_blockt &b)
956+
{
957+
replace_symbolt replace;
958+
code_blockt decls;
959+
960+
const symbolt *argc_sym=nullptr;
961+
if(!ns.lookup("argc'", argc_sym))
962+
{
963+
symbol_exprt argc("argc", argc_sym->type);
964+
replace.insert(argc_sym->name, argc);
965+
code_declt d(argc);
966+
decls.add(d);
967+
}
968+
const symbolt *argv_sym=nullptr;
969+
if(!ns.lookup("argv'", argv_sym))
970+
{
971+
symbol_exprt argv("argv", argv_sym->type);
972+
replace.insert(argv_sym->name, argv);
973+
code_declt d(argv);
974+
decls.add(d);
975+
}
976+
const symbolt *return_sym=nullptr;
977+
if(!ns.lookup("return'", return_sym))
978+
{
979+
symbol_exprt return_value("return_value", return_sym->type);
980+
replace.insert(return_sym->name, return_value);
981+
code_declt d(return_value);
982+
decls.add(d);
983+
}
984+
985+
Forall_operands(it, b)
986+
{
987+
codet &code=to_code(*it);
988+
989+
if(code.get_statement()==ID_function_call)
990+
{
991+
exprt &func=to_code_function_call(code).function();
992+
if(func.id()==ID_symbol)
993+
{
994+
symbol_exprt &s=to_symbol_expr(func);
995+
if(s.get_identifier()==ID_main)
996+
s.set_identifier(CPROVER_PREFIX+id2string(ID_main));
997+
else if(s.get_identifier()==CPROVER_PREFIX "initialize")
998+
continue;
999+
}
1000+
}
1001+
1002+
decls.add(code);
1003+
}
1004+
1005+
b.swap(decls);
1006+
replace(b);
1007+
}
1008+
9491009
void dump_ct::convert_function_declaration(
9501010
const symbolt &symbol,
9511011
const bool skip_main,
@@ -1001,9 +1061,20 @@ void dump_ct::convert_function_declaration(
10011061
converted_enum.swap(converted_e_bak);
10021062
converted_compound.swap(converted_c_bak);
10031063

1064+
if(harness && symbol.name==goto_functions.entry_point())
1065+
cleanup_harness(b);
1066+
10041067
os_body << "// " << symbol.name << '\n';
10051068
os_body << "// " << symbol.location << '\n';
1006-
os_body << make_decl(symbol.name, symbol.type) << '\n';
1069+
if(symbol.name==goto_functions.entry_point())
1070+
os_body << make_decl(ID_main, symbol.type) << '\n';
1071+
else if(!harness || symbol.name!=ID_main)
1072+
os_body << make_decl(symbol.name, symbol.type) << '\n';
1073+
else if(harness && symbol.name==ID_main)
1074+
{
1075+
os_body << make_decl(CPROVER_PREFIX+id2string(symbol.name), symbol.type)
1076+
<< '\n';
1077+
}
10071078
os_body << expr_to_string(b);
10081079
os_body << "\n\n";
10091080

@@ -1017,6 +1088,13 @@ void dump_ct::convert_function_declaration(
10171088
os_decl << "// " << symbol.location << '\n';
10181089
os_decl << make_decl(symbol.name, symbol.type) << ";\n";
10191090
}
1091+
else if(harness && symbol.name==ID_main)
1092+
{
1093+
os_decl << "// " << symbol.name << '\n';
1094+
os_decl << "// " << symbol.location << '\n';
1095+
os_decl << make_decl(CPROVER_PREFIX+id2string(symbol.name), symbol.type)
1096+
<< ";\n";
1097+
}
10201098

10211099
// make sure typedef names used in the function declaration are
10221100
// available
@@ -1368,22 +1446,34 @@ void dump_c(
13681446
const goto_functionst &src,
13691447
const bool use_system_headers,
13701448
const bool use_all_headers,
1449+
const bool include_harness,
13711450
const namespacet &ns,
13721451
std::ostream &out)
13731452
{
13741453
dump_ct goto2c(
1375-
src, use_system_headers, use_all_headers, ns, new_ansi_c_language);
1454+
src,
1455+
use_system_headers,
1456+
use_all_headers,
1457+
include_harness,
1458+
ns,
1459+
new_ansi_c_language);
13761460
out << goto2c;
13771461
}
13781462

13791463
void dump_cpp(
13801464
const goto_functionst &src,
13811465
const bool use_system_headers,
13821466
const bool use_all_headers,
1467+
const bool include_harness,
13831468
const namespacet &ns,
13841469
std::ostream &out)
13851470
{
13861471
dump_ct goto2cpp(
1387-
src, use_system_headers, use_all_headers, ns, new_cpp_language);
1472+
src,
1473+
use_system_headers,
1474+
use_all_headers,
1475+
include_harness,
1476+
ns,
1477+
new_cpp_language);
13881478
out << goto2cpp;
13891479
}

src/goto-instrument/dump_c.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ void dump_c(
1818
const goto_functionst &src,
1919
const bool use_system_headers,
2020
const bool use_all_headers,
21+
const bool include_harness,
2122
const namespacet &ns,
2223
std::ostream &out);
2324

2425
void dump_cpp(
2526
const goto_functionst &src,
2627
const bool use_system_headers,
2728
const bool use_all_headers,
29+
const bool include_harness,
2830
const namespacet &ns,
2931
std::ostream &out);
3032

src/goto-instrument/dump_c_class.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ class dump_ct
2828
const goto_functionst &_goto_functions,
2929
const bool use_system_headers,
3030
const bool use_all_headers,
31+
const bool include_harness,
3132
const namespacet &_ns,
3233
language_factoryt factory):
3334
goto_functions(_goto_functions),
3435
copied_symbol_table(_ns.get_symbol_table()),
3536
ns(copied_symbol_table),
36-
language(factory())
37+
language(factory()),
38+
harness(include_harness)
3739
{
3840
if(use_system_headers)
3941
system_symbols=system_library_symbolst();
@@ -49,6 +51,7 @@ class dump_ct
4951
symbol_tablet copied_symbol_table;
5052
const namespacet ns;
5153
std::unique_ptr<languaget> language;
54+
const bool harness;
5255

5356
typedef std::unordered_set<irep_idt, irep_id_hash> convertedt;
5457
convertedt converted_compound, converted_global, converted_enum;
@@ -158,6 +161,7 @@ class dump_ct
158161
code_declt &decl,
159162
std::list<irep_idt> &local_static,
160163
std::list<irep_idt> &local_type_decls);
164+
void cleanup_harness(code_blockt &b);
161165
};
162166

163167
#endif // CPROVER_GOTO_INSTRUMENT_DUMP_C_CLASS_H

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ int goto_instrument_parse_optionst::doit()
624624
const bool is_cpp=cmdline.isset("dump-cpp");
625625
const bool h_libc=!cmdline.isset("no-system-headers");
626626
const bool h_all=cmdline.isset("use-all-headers");
627+
const bool harness=cmdline.isset("harness");
627628
namespacet ns(symbol_table);
628629

629630
// restore RETURN instructions in case remove_returns had been
@@ -642,11 +643,22 @@ int goto_instrument_parse_optionst::doit()
642643
error() << "failed to write to `" << cmdline.args[1] << "'";
643644
return 10;
644645
}
645-
(is_cpp ? dump_cpp : dump_c)(goto_functions, h_libc, h_all, ns, out);
646+
(is_cpp ? dump_cpp : dump_c)(
647+
goto_functions,
648+
h_libc,
649+
h_all,
650+
harness,
651+
ns,
652+
out);
646653
}
647654
else
648655
(is_cpp ? dump_cpp : dump_c)(
649-
goto_functions, h_libc, h_all, ns, std::cout);
656+
goto_functions,
657+
h_libc,
658+
h_all,
659+
harness,
660+
ns,
661+
std::cout);
650662

651663
return 0;
652664
}
@@ -1545,6 +1557,7 @@ void goto_instrument_parse_optionst::help()
15451557
"Other options:\n"
15461558
" --no-system-headers with --dump-c/--dump-cpp: generate C source expanding libc includes\n" // NOLINT(*)
15471559
" --use-all-headers with --dump-c/--dump-cpp: generate C source with all includes\n" // NOLINT(*)
1560+
" --harness with --dump-c/--dump-cpp: include input generator in output\n" // NOLINT(*)
15481561
" --version show version and exit\n"
15491562
" --xml-ui use XML-formatted output\n"
15501563
" --json-ui use JSON-formatted output\n"

src/goto-instrument/goto_instrument_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Author: Daniel Kroening, [email protected]
2727
"(document-claims-latex)(document-claims-html)" \
2828
"(document-properties-latex)(document-properties-html)" \
2929
"(dump-c)(dump-cpp)(no-system-headers)(use-all-headers)(dot)(xml)" \
30+
"(harness)" \
3031
OPT_GOTO_CHECK \
3132
/* no-X-check are deprecated and ignored */ \
3233
"(no-bounds-check)(no-pointer-check)(no-div-by-zero-check)" \

0 commit comments

Comments
 (0)