CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
static_simplifier.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: goto-analyzer
4
5Author: Martin Brain, martin.brain@cs.ox.ac.uk
6
7\*******************************************************************/
8
9#include "static_simplifier.h"
10
11#include <util/message.h>
12#include <util/options.h>
13
19
20#include <analyses/ai.h>
21
30 goto_modelt &goto_model,
31 const ai_baset &ai,
32 const optionst &options,
33 message_handlert &message_handler,
34 std::ostream &out)
35{
36 struct counterst
37 {
38 counterst() :
39 asserts(0),
40 assumes(0),
41 gotos(0),
42 assigns(0),
43 function_calls(0) {}
44
45 std::size_t asserts;
46 std::size_t assumes;
47 std::size_t gotos;
48 std::size_t assigns;
49 std::size_t function_calls;
50 };
51
52 counterst simplified;
53 counterst unmodified;
54
55 namespacet ns(goto_model.symbol_table);
56
57 messaget m(message_handler);
58 m.status() << "Simplifying program" << messaget::eom;
59 m.warning() << "**** WARNING: This simplification is currently known to be "
60 "unsound for input programs which include recursion. Do not "
61 "use it if soundness is important for your use case."
63
64 for(auto &gf_entry : goto_model.goto_functions.function_map)
65 {
67 {
68 m.progress() << "Simplifying " << gf_entry.first << messaget::eom;
69
70 if(i_it->is_assert())
71 {
72 exprt cond = i_it->condition();
73
74 bool unchanged = ai.abstract_state_before(i_it)->ai_simplify(cond, ns);
75
76 if(unchanged)
77 unmodified.asserts++;
78 else
79 {
80 simplified.asserts++;
81 i_it->condition_nonconst() = cond;
82 }
83 }
84 else if(i_it->is_assume())
85 {
86 exprt cond = i_it->condition();
87
88 bool unchanged = ai.abstract_state_before(i_it)->ai_simplify(cond, ns);
89
90 if(unchanged)
91 unmodified.assumes++;
92 else
93 {
94 simplified.assumes++;
95 i_it->condition_nonconst() = cond;
96 }
97 }
98 else if(i_it->is_goto())
99 {
100 exprt cond = i_it->condition();
101
102 bool unchanged = ai.abstract_state_before(i_it)->ai_simplify(cond, ns);
103
104 if(unchanged)
105 unmodified.gotos++;
106 else
107 {
108 simplified.gotos++;
109 i_it->condition_nonconst() = cond;
110 }
111 }
112 else if(i_it->is_assign())
113 {
114 // Simplification needs to be aware of which side of the
115 // expression it is handling as:
116 // <i=0, j=1> i=j
117 // should simplify to i=1, not to 0=1.
118
119 bool unchanged_lhs = ai.abstract_state_before(i_it)->ai_simplify_lhs(
120 i_it->assign_lhs_nonconst(), ns);
121
122 bool unchanged_rhs = ai.abstract_state_before(i_it)->ai_simplify(
123 i_it->assign_rhs_nonconst(), ns);
124
126 unmodified.assigns++;
127 else
128 simplified.assigns++;
129 }
130 else if(i_it->is_function_call())
131 {
132 // copy
133 auto call_function = as_const(*i_it).call_function();
134 auto call_arguments = as_const(*i_it).call_arguments();
135
136 bool unchanged =
137 ai.abstract_state_before(i_it)->ai_simplify(call_function, ns);
138
139 for(auto &o : call_arguments)
140 unchanged &= ai.abstract_state_before(i_it)->ai_simplify(o, ns);
141
142 if(unchanged)
143 unmodified.function_calls++;
144 else
145 {
146 simplified.function_calls++;
147 i_it->call_function() = std::move(call_function);
148 i_it->call_arguments() = std::move(call_arguments);
149 }
150 }
151 }
152 }
153
154 // Make sure the references are correct.
155 goto_model.goto_functions.update();
156
157 m.status() << "Simplified: "
158 << " assert: " << simplified.asserts
159 << ", assume: " << simplified.assumes
160 << ", goto: " << simplified.gotos
161 << ", assigns: " << simplified.assigns
162 << ", function calls: " << simplified.function_calls
163 << "\n"
164 << "Unmodified: "
165 << " assert: " << unmodified.asserts
166 << ", assume: " << unmodified.assumes
167 << ", goto: " << unmodified.gotos
168 << ", assigns: " << unmodified.assigns
169 << ", function calls: " << unmodified.function_calls
170 << messaget::eom;
171
172
173 // Remove obviously unreachable things and (now) unconditional branches
174 if(options.get_bool_option("simplify-slicing"))
175 {
176 m.status() << "Removing unreachable instructions" << messaget::eom;
177
178 // Removes goto false
179 remove_skip(goto_model);
180
181 // Convert unreachable to skips
183
184 // Remove all of the new skips
185 remove_skip(goto_model);
186 }
187
188 // restore return types before writing the binary
189 restore_returns(goto_model);
190 goto_model.goto_functions.update();
191
192 m.status() << "Writing goto binary" << messaget::eom;
193 return write_goto_binary(out,
194 ns.get_symbol_table(),
195 goto_model.goto_functions);
196}
Abstract Interpretation.
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition as_const.h:14
This is the basic interface of the abstract interpreter with default implementations of the core func...
Definition ai.h:117
virtual cstate_ptrt abstract_state_before(locationt l) const
Get a copy of the abstract state before the given instruction, without needing to know what kind of d...
Definition ai.h:221
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Base class for all expressions.
Definition expr.h:56
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
Definition goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
mstreamt & warning() const
Definition message.h:396
mstreamt & progress() const
Definition message.h:416
static eomt eom
Definition message.h:289
mstreamt & status() const
Definition message.h:406
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition namespace.h:123
bool get_bool_option(const std::string &option) const
Definition options.cpp:44
Symbol Table + CFG.
#define Forall_goto_program_instructions(it, program)
Options.
void restore_returns(goto_modelt &goto_model)
restores return statements
Replace function returns by assignments to global variables.
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
Program Transformation.
void remove_unreachable(goto_programt &goto_program)
remove unreachable code
Program Transformation.
bool static_simplifier(goto_modelt &goto_model, const ai_baset &ai, const optionst &options, message_handlert &message_handler, std::ostream &out)
Simplifies the program using the information in the abstract domain.
static void write_goto_binary(std::ostream &out, const symbol_table_baset &symbol_table, const goto_functionst &goto_functions, irep_serializationt &irepconverter)
Writes a goto program to disc, using goto binary format.
Write GOTO binaries.