@@ -39,6 +39,7 @@ Date: February 2016
39
39
#include < util/pointer_offset_size.h>
40
40
#include < util/pointer_predicates.h>
41
41
#include < util/replace_symbol.h>
42
+ #include < util/simplify_expr.h>
42
43
#include < util/std_code.h>
43
44
44
45
#include " memory_predicates.h"
@@ -1105,7 +1106,9 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
1105
1106
return true ;
1106
1107
}
1107
1108
1108
- if (check_for_looped_mallocs (function_obj->second .body ))
1109
+ auto &goto_program = function_obj->second .body ;
1110
+
1111
+ if (check_for_looped_mallocs (goto_program))
1109
1112
{
1110
1113
return true ;
1111
1114
}
@@ -1126,14 +1129,17 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
1126
1129
for (const auto ¶m : to_code_type (target.type ).parameters ())
1127
1130
assigns.add_to_write_set (ns.lookup (param.get_identifier ()).symbol_expr ());
1128
1131
1129
- auto instruction_it = function_obj-> second . body .instructions .begin ();
1132
+ auto instruction_it = goto_program .instructions .begin ();
1130
1133
for (const auto &car : assigns.get_write_set ())
1131
1134
{
1132
1135
auto snapshot_instructions = car.generate_snapshot_instructions ();
1133
1136
insert_before_swap_and_advance (
1134
- function_obj-> second . body , instruction_it, snapshot_instructions);
1137
+ goto_program , instruction_it, snapshot_instructions);
1135
1138
};
1136
1139
1140
+ // restore internal coherence in the programs
1141
+ goto_functions.update ();
1142
+
1137
1143
// Full inlining of the function body
1138
1144
// Inlining is performed so that function calls to a same function
1139
1145
// occurring under different write sets get instrumented specifically
@@ -1145,9 +1151,17 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
1145
1151
decorated.get_recursive_function_warnings_count () == 0 ,
1146
1152
" Recursive functions found during inlining" );
1147
1153
1148
- // restore internal invariants
1154
+ // clean up possible fake loops that are due to `IF 0!=0 GOTO i` instructions
1155
+ simplify_gotos (goto_program);
1156
+
1157
+ // restore internal coherence in the programs
1149
1158
goto_functions.update ();
1150
1159
1160
+ INVARIANT (
1161
+ is_loop_free (goto_program),
1162
+ " Loops remain in function '" + id2string (function) +
1163
+ " ', assigns clause checking instrumentation cannot be applied." );
1164
+
1151
1165
// Insert write set inclusion checks.
1152
1166
check_frame_conditions (
1153
1167
function_obj->first ,
@@ -1613,3 +1627,62 @@ bool code_contractst::is_auxiliary_decl_dead_or_assign(
1613
1627
return false ;
1614
1628
}
1615
1629
1630
+ void code_contractst::simplify_gotos (goto_programt &goto_program)
1631
+ {
1632
+ for (auto &instruction : goto_program.instructions )
1633
+ {
1634
+ if (instruction.is_goto ())
1635
+ {
1636
+ const auto &condition = instruction.get_condition ();
1637
+ const auto &simplified = simplify_expr (condition, ns);
1638
+ if (simplified.is_false ())
1639
+ instruction.turn_into_skip ();
1640
+ }
1641
+ }
1642
+ }
1643
+
1644
+ bool code_contractst::is_loop_free (const goto_programt &goto_program)
1645
+ {
1646
+ // create cfg from instruction list
1647
+ cfg_baset<empty_cfg_nodet> cfg;
1648
+ cfg (goto_program);
1649
+
1650
+ // check that all nodes are there
1651
+ INVARIANT (
1652
+ goto_program.instructions .size () == cfg.size (),
1653
+ " Instruction list vs CFG size mismatch." );
1654
+
1655
+ // compute SCCs
1656
+ std::vector<node_indext> node_to_scc (cfg.size (), -1 );
1657
+ auto nof_sccs = cfg.SCCs (node_to_scc);
1658
+
1659
+ // compute size of each SCC
1660
+ std::vector<int > scc_size (nof_sccs, 0 );
1661
+ for (auto scc : node_to_scc)
1662
+ {
1663
+ INVARIANT (
1664
+ 0 <= scc && scc < nof_sccs, " Could not determine SCC for instruction" );
1665
+ scc_size[scc]++;
1666
+ }
1667
+
1668
+ // check they are all of size 1
1669
+ for (int scc_id = 0 ; scc_id < nof_sccs; scc_id++)
1670
+ {
1671
+ auto size = scc_size[scc_id];
1672
+ if (size > 1 )
1673
+ {
1674
+ log.error () << " Found CFG SCC with size " << size << messaget::eom;
1675
+ for (const auto &node_id : node_to_scc)
1676
+ {
1677
+ if (node_to_scc[node_id] == scc_id)
1678
+ {
1679
+ const auto &pc = cfg[node_id].PC ;
1680
+ goto_program.output_instruction (ns, " " , log.error (), *pc);
1681
+ log.error () << messaget::eom;
1682
+ }
1683
+ }
1684
+ return false ;
1685
+ }
1686
+ }
1687
+ return true ;
1688
+ }
0 commit comments