Skip to content

Commit f0f6dca

Browse files
author
Remi Delmas
committed
move functions to utils.cpp
1 parent 3cdf2be commit f0f6dca

File tree

4 files changed

+143
-126
lines changed

4 files changed

+143
-126
lines changed

src/goto-instrument/contracts/contracts.cpp

Lines changed: 4 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ Date: February 2016
4040
#include <util/pointer_offset_size.h>
4141
#include <util/pointer_predicates.h>
4242
#include <util/replace_symbol.h>
43-
#include <util/simplify_expr.h>
4443
#include <util/std_code.h>
4544

4645
#include "memory_predicates.h"
@@ -1175,13 +1174,13 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
11751174
"Recursive functions found during inlining");
11761175

11771176
// clean up possible fake loops that are due to `IF 0!=0 GOTO i` instructions
1178-
simplify_gotos(goto_program);
1177+
simplify_gotos(goto_program, ns);
11791178

11801179
// restore internal coherence in the programs
11811180
goto_functions.update();
11821181

11831182
INVARIANT(
1184-
is_loop_free(goto_program),
1183+
is_loop_free(goto_program, ns, log),
11851184
"Loops remain in function '" + id2string(function) +
11861185
"', assigns clause checking instrumentation cannot be applied.");
11871186

@@ -1212,10 +1211,10 @@ void code_contractst::check_frame_conditions(
12121211
if(pragmas.find(CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK) != pragmas.end())
12131212
continue;
12141213

1215-
if(skip_parameter_assigns && is_parameter_assign(instruction_it))
1214+
if(skip_parameter_assigns && is_parameter_assign(instruction_it, ns))
12161215
continue;
12171216

1218-
if(is_auxiliary_decl_dead_or_assign(instruction_it))
1217+
if(is_auxiliary_decl_dead_or_assign(instruction_it, ns))
12191218
continue;
12201219

12211220
// Do not instrument this instruction again in the future,
@@ -1605,107 +1604,3 @@ bool code_contractst::enforce_contracts(const std::set<std::string> &to_enforce)
16051604
}
16061605
return fail;
16071606
}
1608-
1609-
bool code_contractst::is_parameter_assign(
1610-
const goto_programt::targett &instruction_it)
1611-
{
1612-
optionalt<symbol_exprt> sym = {};
1613-
1614-
// extract symbol
1615-
if(instruction_it->is_assign())
1616-
{
1617-
const auto &lhs = instruction_it->assign_lhs();
1618-
if(can_cast_expr<symbol_exprt>(lhs))
1619-
sym = to_symbol_expr(lhs);
1620-
}
1621-
1622-
// check condition
1623-
if(sym.has_value())
1624-
return ns.lookup(sym.value().get_identifier()).is_parameter;
1625-
1626-
return false;
1627-
}
1628-
1629-
bool code_contractst::is_auxiliary_decl_dead_or_assign(
1630-
const goto_programt::targett &instruction_it)
1631-
{
1632-
optionalt<symbol_exprt> sym = {};
1633-
1634-
// extract symbol
1635-
if(instruction_it->is_decl())
1636-
sym = instruction_it->decl_symbol();
1637-
else if(instruction_it->is_dead())
1638-
sym = instruction_it->dead_symbol();
1639-
else if(instruction_it->is_assign())
1640-
{
1641-
const auto &lhs = instruction_it->assign_lhs();
1642-
if(can_cast_expr<symbol_exprt>(lhs))
1643-
sym = to_symbol_expr(lhs);
1644-
}
1645-
1646-
// check condition
1647-
if(sym.has_value())
1648-
return ns.lookup(sym.value().get_identifier()).is_auxiliary;
1649-
1650-
return false;
1651-
}
1652-
1653-
void code_contractst::simplify_gotos(goto_programt &goto_program)
1654-
{
1655-
for(auto &instruction : goto_program.instructions)
1656-
{
1657-
if(instruction.is_goto())
1658-
{
1659-
const auto &condition = instruction.get_condition();
1660-
const auto &simplified = simplify_expr(condition, ns);
1661-
if(simplified.is_false())
1662-
instruction.turn_into_skip();
1663-
}
1664-
}
1665-
}
1666-
1667-
bool code_contractst::is_loop_free(const goto_programt &goto_program)
1668-
{
1669-
// create cfg from instruction list
1670-
cfg_baset<empty_cfg_nodet> cfg;
1671-
cfg(goto_program);
1672-
1673-
// check that all nodes are there
1674-
INVARIANT(
1675-
goto_program.instructions.size() == cfg.size(),
1676-
"Instruction list vs CFG size mismatch.");
1677-
1678-
// compute SCCs
1679-
std::vector<node_indext> node_to_scc(cfg.size(), -1);
1680-
auto nof_sccs = cfg.SCCs(node_to_scc);
1681-
1682-
// compute size of each SCC
1683-
std::vector<int> scc_size(nof_sccs, 0);
1684-
for(auto scc : node_to_scc)
1685-
{
1686-
INVARIANT(
1687-
0 <= scc && scc < nof_sccs, "Could not determine SCC for instruction");
1688-
scc_size[scc]++;
1689-
}
1690-
1691-
// check they are all of size 1
1692-
for(size_t scc_id = 0; scc_id < nof_sccs; scc_id++)
1693-
{
1694-
auto size = scc_size[scc_id];
1695-
if(size > 1)
1696-
{
1697-
log.error() << "Found CFG SCC with size " << size << messaget::eom;
1698-
for(const auto &node_id : node_to_scc)
1699-
{
1700-
if(node_to_scc[node_id] == scc_id)
1701-
{
1702-
const auto &pc = cfg[node_id].PC;
1703-
goto_program.output_instruction(ns, "", log.error(), *pc);
1704-
log.error() << messaget::eom;
1705-
}
1706-
}
1707-
return false;
1708-
}
1709-
}
1710-
return true;
1711-
}

src/goto-instrument/contracts/contracts.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -213,23 +213,6 @@ class code_contractst
213213
source_locationt location,
214214
const irep_idt &mode);
215215

216-
private:
217-
/// Returns true iff the instruction is a `DECL x`, `DEAD x`,
218-
/// or `ASSIGN x := expr` where `x` has the `is_parameter` flag set.
219-
bool is_parameter_assign(const goto_programt::targett &instruction_it);
220-
221-
/// Returns true iff the instruction is a `DECL x`, `DEAD x`,
222-
/// or `ASSIGN x := expr` where `x` has the `is_auxiliary` flag set.
223-
bool is_auxiliary_decl_dead_or_assign(
224-
const goto_programt::targett &instruction_it);
225-
226-
/// Turns goto instructions `IF cond GOTO label` where the condition
227-
/// statically simplifies to `false` into SKIP instructions.
228-
void simplify_gotos(goto_programt &goto_program);
229-
230-
/// Returns true iff the given program is loop-free,
231-
/// i.e. if each SCC of its CFG contains a single element.
232-
bool is_loop_free(const goto_programt &goto_program);
233216
};
234217

235218
#endif // CPROVER_GOTO_INSTRUMENT_CONTRACTS_CONTRACTS_H

src/goto-instrument/contracts/utils.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ Date: September 2021
1010

1111
#include "utils.h"
1212

13+
#include <goto-programs/cfg.h>
1314
#include <util/fresh_symbol.h>
15+
#include <util/graph.h>
16+
#include <util/message.h>
1417
#include <util/pointer_expr.h>
1518
#include <util/pointer_predicates.h>
19+
#include <util/simplify_expr.h>
1620

1721
goto_programt::instructiont &
1822
add_pragma_disable_assigns_check(goto_programt::instructiont &instr)
@@ -163,3 +167,113 @@ void disable_pointer_checks(source_locationt &source_location)
163167
source_location.add_pragma("disable:pointer-primitive-check");
164168
source_location.add_pragma("disable:pointer-overflow-check");
165169
}
170+
171+
bool is_parameter_assign(
172+
const goto_programt::targett &instruction_it,
173+
namespacet &ns)
174+
{
175+
optionalt<symbol_exprt> sym = {};
176+
177+
// extract symbol
178+
if(instruction_it->is_assign())
179+
{
180+
const auto &lhs = instruction_it->assign_lhs();
181+
if(can_cast_expr<symbol_exprt>(lhs))
182+
sym = to_symbol_expr(lhs);
183+
}
184+
185+
// check condition
186+
if(sym.has_value())
187+
return ns.lookup(sym.value().get_identifier()).is_parameter;
188+
189+
return false;
190+
}
191+
192+
bool is_auxiliary_decl_dead_or_assign(
193+
const goto_programt::targett &instruction_it,
194+
namespacet &ns)
195+
{
196+
optionalt<symbol_exprt> sym = {};
197+
198+
// extract symbol
199+
if(instruction_it->is_decl())
200+
sym = instruction_it->decl_symbol();
201+
else if(instruction_it->is_dead())
202+
sym = instruction_it->dead_symbol();
203+
else if(instruction_it->is_assign())
204+
{
205+
const auto &lhs = instruction_it->assign_lhs();
206+
if(can_cast_expr<symbol_exprt>(lhs))
207+
sym = to_symbol_expr(lhs);
208+
}
209+
210+
// check condition
211+
if(sym.has_value())
212+
return ns.lookup(sym.value().get_identifier()).is_auxiliary;
213+
214+
return false;
215+
}
216+
217+
void simplify_gotos(goto_programt &goto_program, namespacet &ns)
218+
{
219+
for(auto &instruction : goto_program.instructions)
220+
{
221+
if(instruction.is_goto())
222+
{
223+
const auto &condition = instruction.get_condition();
224+
const auto &simplified = simplify_expr(condition, ns);
225+
if(simplified.is_false())
226+
instruction.turn_into_skip();
227+
}
228+
}
229+
}
230+
231+
bool is_loop_free(
232+
const goto_programt &goto_program,
233+
namespacet &ns,
234+
messaget &log)
235+
{
236+
// create cfg from instruction list
237+
cfg_baset<empty_cfg_nodet> cfg;
238+
cfg(goto_program);
239+
240+
// check that all nodes are there
241+
INVARIANT(
242+
goto_program.instructions.size() == cfg.size(),
243+
"Instruction list vs CFG size mismatch.");
244+
245+
// compute SCCs
246+
using idxt = graph_nodet<empty_cfg_nodet>::node_indext;
247+
std::vector<idxt> node_to_scc(cfg.size(), -1);
248+
auto nof_sccs = cfg.SCCs(node_to_scc);
249+
250+
// compute size of each SCC
251+
std::vector<int> scc_size(nof_sccs, 0);
252+
for(auto scc : node_to_scc)
253+
{
254+
INVARIANT(
255+
0 <= scc && scc < nof_sccs, "Could not determine SCC for instruction");
256+
scc_size[scc]++;
257+
}
258+
259+
// check they are all of size 1
260+
for(size_t scc_id = 0; scc_id < nof_sccs; scc_id++)
261+
{
262+
auto size = scc_size[scc_id];
263+
if(size > 1)
264+
{
265+
log.error() << "Found CFG SCC with size " << size << messaget::eom;
266+
for(const auto &node_id : node_to_scc)
267+
{
268+
if(node_to_scc[node_id] == scc_id)
269+
{
270+
const auto &pc = cfg[node_id].PC;
271+
goto_program.output_instruction(ns, "", log.error(), *pc);
272+
log.error() << messaget::eom;
273+
}
274+
}
275+
return false;
276+
}
277+
}
278+
return true;
279+
}

src/goto-instrument/contracts/utils.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Date: September 2021
1717

1818
#include <goto-programs/goto_model.h>
1919

20+
#include <util/message.h>
21+
2022
#define CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK "contracts:disable:assigns-check"
2123

2224
/// \brief A class that overrides the low-level havocing functions in the base
@@ -125,4 +127,27 @@ const symbolt &new_tmp_symbol(
125127
/// Add disable pragmas for all pointer checks on the given location
126128
void disable_pointer_checks(source_locationt &source_location);
127129

130+
/// Returns true iff the instruction is a `DECL x`, `DEAD x`,
131+
/// or `ASSIGN x := expr` where `x` has the `is_parameter` flag set.
132+
bool is_parameter_assign(
133+
const goto_programt::targett &instruction_it,
134+
namespacet &ns);
135+
136+
/// Returns true iff the instruction is a `DECL x`, `DEAD x`,
137+
/// or `ASSIGN x := expr` where `x` has the `is_auxiliary` flag set.
138+
bool is_auxiliary_decl_dead_or_assign(
139+
const goto_programt::targett &instruction_it,
140+
namespacet &ns);
141+
142+
/// Turns goto instructions `IF cond GOTO label` where the condition
143+
/// statically simplifies to `false` into SKIP instructions.
144+
void simplify_gotos(goto_programt &goto_program, namespacet &ns);
145+
146+
/// Returns true iff the given program is loop-free,
147+
/// i.e. if each SCC of its CFG contains a single element.
148+
bool is_loop_free(
149+
const goto_programt &goto_program,
150+
namespacet &ns,
151+
messaget &log);
152+
128153
#endif // CPROVER_GOTO_INSTRUMENT_CONTRACTS_UTILS_H

0 commit comments

Comments
 (0)