Skip to content

Commit 971df90

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Initial attempt at introducing well-formedness checking for SSA
Follows the #3123 skeleton with additional checks in SSA_stept.
1 parent 9d6ab32 commit 971df90

8 files changed

+101
-2
lines changed

src/cbmc/bmc.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,10 @@ void bmct::perform_symbolic_execution(
638638
goto_symext::get_goto_functiont get_goto_function)
639639
{
640640
symex.symex_from_entry_point_of(get_goto_function, symex_symbol_table);
641+
if(options.get_bool_option("validate-ssa-equation"))
642+
{
643+
symex.validate(ns, validation_modet::INVARIANT);
644+
}
641645
INVARIANT(
642646
options.get_bool_option("paths") || path_storage.empty(),
643647
"Branch points were saved even though we should have been "

src/cbmc/cbmc_parse_options.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,11 @@ int cbmc_parse_optionst::doit()
536536
goto_model.validate(ns, validation_modet::INVARIANT);
537537
}
538538

539+
if(cmdline.isset("validate-ssa-equation"))
540+
{
541+
options.set_option("validate-ssa-equation", true);
542+
}
543+
539544
return bmct::do_language_agnostic_bmc(
540545
path_strategy_chooser, options, goto_model, ui_message_handler);
541546
}
@@ -986,6 +991,9 @@ void cbmc_parse_optionst::help()
986991
// NOLINTNEXTLINE(whitespace/line_length)
987992
" --validate-goto-model enable additional well-formedness checks on the\n"
988993
" goto program\n"
994+
// NOLINTNEXTLINE(whitespace/line_length)
995+
" --validate-ssa-equation enable additional well-formedness checks on the\n"
996+
" SSA equation\n"
989997
HELP_GOTO_TRACE
990998
HELP_FLUSH
991999
" --verbosity # verbosity level\n"

src/cbmc/cbmc_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class optionst;
7474
"(localize-faults)(localize-faults-method):" \
7575
OPT_GOTO_TRACE \
7676
"(validate-goto-model)" \
77+
"(validate-ssa-equation)" \
7778
"(claim):(show-claims)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)
7879
// clang-format on
7980

src/goto-symex/goto_symex.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,11 @@ class goto_symext
512512
"attempting to read remaining_vccs");
513513
return _remaining_vccs;
514514
}
515+
516+
void validate(const namespacet &ns, const validation_modet vm) const
517+
{
518+
target.validate(ns, vm);
519+
}
515520
};
516521

517522
#endif // CPROVER_GOTO_SYMEX_GOTO_SYMEX_H

src/goto-symex/symex_target_equation.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "symex_target_equation.h"
1313

14+
#include <util/base_type.h>
1415
#include <util/format_expr.h>
1516
#include <util/std_expr.h>
1617
#include <util/throw_with_nested.h>
@@ -976,3 +977,56 @@ void symex_target_equationt::SSA_stept::output(std::ostream &out) const
976977

977978
out << "Guard: " << format(guard) << '\n';
978979
}
980+
981+
/// Check that the SSA step is well-formed
982+
/// \param ns namespace to lookup identifiers
983+
/// \param vm validation mode to be used for reporting failures
984+
void symex_target_equationt::SSA_stept::validate(
985+
const namespacet &ns,
986+
const validation_modet vm) const
987+
{
988+
validate_expr_full_pick(guard, ns, vm);
989+
990+
switch(type)
991+
{
992+
case goto_trace_stept::typet::ASSERT:
993+
case goto_trace_stept::typet::ASSUME:
994+
case goto_trace_stept::typet::GOTO:
995+
case goto_trace_stept::typet::CONSTRAINT:
996+
validate_expr_full_pick(cond_expr, ns, vm);
997+
break;
998+
case goto_trace_stept::typet::ASSIGNMENT:
999+
case goto_trace_stept::typet::DECL:
1000+
validate_expr_full_pick(ssa_lhs, ns, vm);
1001+
validate_expr_full_pick(ssa_full_lhs, ns, vm);
1002+
validate_expr_full_pick(original_full_lhs, ns, vm);
1003+
validate_expr_full_pick(ssa_rhs, ns, vm);
1004+
base_type_eq(ssa_lhs.get_original_expr(), ssa_rhs, ns);
1005+
break;
1006+
case goto_trace_stept::typet::INPUT:
1007+
case goto_trace_stept::typet::OUTPUT:
1008+
for(const auto &expr : io_args)
1009+
validate_expr_full_pick(expr, ns, vm);
1010+
break;
1011+
case goto_trace_stept::typet::FUNCTION_CALL:
1012+
for(const auto &expr : ssa_function_arguments)
1013+
validate_expr_full_pick(expr, ns, vm);
1014+
case goto_trace_stept::typet::FUNCTION_RETURN:
1015+
{
1016+
const symbolt *symbol;
1017+
DATA_CHECK(
1018+
!ns.lookup(function_identifier, symbol), "unknown function identifier");
1019+
}
1020+
break;
1021+
case goto_trace_stept::typet::NONE:
1022+
case goto_trace_stept::typet::LOCATION:
1023+
case goto_trace_stept::typet::DEAD:
1024+
case goto_trace_stept::typet::SHARED_READ:
1025+
case goto_trace_stept::typet::SHARED_WRITE:
1026+
case goto_trace_stept::typet::SPAWN:
1027+
case goto_trace_stept::typet::MEMORY_BARRIER:
1028+
case goto_trace_stept::typet::ATOMIC_BEGIN:
1029+
case goto_trace_stept::typet::ATOMIC_END:
1030+
break;
1031+
}
1032+
}

src/goto-symex/symex_target_equation.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Author: Daniel Kroening, [email protected]
1515
#include <list>
1616
#include <iosfwd>
1717

18-
#include <util/invariant.h>
1918
#include <util/merge_irep.h>
19+
#include <util/validate.h>
2020

2121
#include <goto-programs/goto_program.h>
2222
#include <goto-programs/goto_trace.h>
@@ -268,6 +268,8 @@ class symex_target_equationt:public symex_targett
268268
std::ostream &out) const;
269269

270270
void output(std::ostream &out) const;
271+
272+
void validate(const namespacet &ns, const validation_modet vm) const;
271273
};
272274

273275
std::size_t count_assertions() const
@@ -324,6 +326,12 @@ class symex_target_equationt:public symex_targett
324326
return false;
325327
}
326328

329+
void validate(const namespacet &ns, const validation_modet vm) const
330+
{
331+
for(const SSA_stept &step : SSA_steps)
332+
step.validate(ns, vm);
333+
}
334+
327335
protected:
328336
// for enforcing sharing in the expressions stored
329337
merge_irept merge_irep;

src/util/ssa_expr.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,21 @@ class ssa_exprt:public symbol_exprt
139139
/* Used to determine whether or not an identifier can be built
140140
* before trying and getting an exception */
141141
static bool can_build_identifier(const exprt &src);
142+
143+
void check(const validation_modet vm = validation_modet::INVARIANT) const
144+
{
145+
DATA_CHECK(!has_operands(), "SSA expression should not have operands");
146+
DATA_CHECK(id() == ID_symbol, "SSA expression symbols are symbols");
147+
DATA_CHECK(get_bool(ID_C_SSA_symbol), "wrong SSA expression ID");
148+
}
149+
150+
void validate(
151+
const namespacet &ns,
152+
const validation_modet vm = validation_modet::INVARIANT) const
153+
{
154+
check(vm);
155+
validate_expr_full_pick(get_original_expr(), ns, vm);
156+
}
142157
};
143158

144159
/*! \brief Cast a generic exprt to an \ref ssa_exprt

src/util/validate_expressions.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Author: Daniel Poetzl
1414

1515
#include "expr.h"
1616
#include "namespace.h"
17-
#include "std_expr.h"
17+
#include "ssa_expr.h"
1818
#include "validate.h"
1919

2020
#define CALL_ON_EXPR(expr_type) \
@@ -31,6 +31,10 @@ void call_on_expr(const exprt &expr, Args &&... args)
3131
{
3232
CALL_ON_EXPR(plus_exprt);
3333
}
34+
else if(expr.get_bool(ID_C_SSA_symbol))
35+
{
36+
CALL_ON_EXPR(ssa_exprt);
37+
}
3438
else
3539
{
3640
#ifdef REPORT_UNIMPLEMENTED_EXPRESSION_CHECKS

0 commit comments

Comments
 (0)