CBMC
Loading...
Searching...
No Matches
remove_skip.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Program Transformation
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "remove_skip.h"
13#include "goto_model.h"
14
15#include <util/std_code.h>
16
28 const goto_programt &body,
30 bool ignore_labels)
31{
32 if(!ignore_labels && !it->labels.empty())
33 return false;
34
35 if(it->is_skip())
36 return !it->code().get_bool(ID_explicit);
37
38 if(it->is_goto())
39 {
40 if(it->condition().is_false())
41 return true;
42
44 next_it++;
45
46 if(next_it == body.instructions.end())
47 return false;
48
49 // A branch to the next instruction is a skip
50 // We also require the guard to be 'true'
51 return it->condition().is_true() && it->get_target() == next_it;
52 }
53
54 if(it->is_other())
55 {
56 if(it->get_other().is_nil())
57 return true;
58
59 const irep_idt &statement = it->get_other().get_statement();
60
61 if(statement==ID_skip)
62 return true;
63 else if(statement==ID_expression)
64 {
66 const exprt &expr=code_expression.expression();
67 if(expr.id()==ID_typecast &&
68 expr.type().id()==ID_empty &&
69 to_typecast_expr(expr).op().is_constant())
70 {
71 // something like (void)0
72 return true;
73 }
74 }
75
76 return false;
77 }
78
79 return false;
80}
81
88 goto_programt &goto_program,
91{
92 // This needs to be a fixed-point, as
93 // removing a skip can turn a goto into a skip.
94 std::size_t old_size;
95
96 do
97 {
98 old_size=goto_program.instructions.size();
99
100 // maps deleted instructions to their replacement
101 typedef std::map<
107
108 // remove skip statements
109
110 for(goto_programt::instructionst::iterator it = begin; it != end;)
111 {
113
114 // for collecting labels
115 std::list<irep_idt> labels;
116
117 while(is_skip(goto_program, it, true))
118 {
119 // don't remove the last skip statement,
120 // it could be a target
121 if(
122 it == std::prev(end) ||
123 (std::next(it)->is_end_function() &&
124 (!labels.empty() || !it->labels.empty())))
125 {
126 break;
127 }
128
129 // save labels
130 labels.splice(labels.end(), it->labels);
131 it++;
132 }
133
135
136 // save labels
137 it->labels.splice(it->labels.begin(), labels);
138
140 {
142 new_targets[old_target]=new_target; // remember the old targets
143 }
144 else
145 it++;
146 }
147
148 // adjust gotos across the full goto program body
149 for(auto &ins : goto_program.instructions)
150 {
151 if(ins.is_goto() || ins.is_start_thread() || ins.is_catch())
152 {
153 for(auto &target : ins.targets)
154 {
155 new_targetst::const_iterator result = new_targets.find(target);
156
157 if(result!=new_targets.end())
158 target = result->second;
159 }
160 }
161 }
162
163 while(new_targets.find(begin) != new_targets.end())
164 ++begin;
165
166 // now delete the skips -- we do so after adjusting the
167 // gotos to avoid dangling targets
168 for(const auto &new_target : new_targets)
169 goto_program.instructions.erase(new_target.first);
170
171 // remove the last skip statement unless it's a target
172 goto_program.compute_target_numbers();
173
174 if(begin != end)
175 {
176 goto_programt::targett last = std::prev(end);
177 if(begin == last)
178 ++begin;
179
180 if(is_skip(goto_program, last) && !last->is_target())
181 goto_program.instructions.erase(last);
182 }
183 }
184 while(goto_program.instructions.size()<old_size);
185}
186
188void remove_skip(goto_programt &goto_program)
189{
191 goto_program,
192 goto_program.instructions.begin(),
193 goto_program.instructions.end());
194
195 goto_program.update();
196}
197
199void remove_skip(goto_functionst &goto_functions)
200{
201 for(auto &gf_entry : goto_functions.function_map)
202 {
204 gf_entry.second.body,
205 gf_entry.second.body.instructions.begin(),
206 gf_entry.second.body.instructions.end());
207 }
208
209 // we may remove targets
210 goto_functions.update();
211}
212
213void remove_skip(goto_modelt &goto_model)
214{
215 remove_skip(goto_model.goto_functions);
216}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
codet representation of an expression statement.
Definition std_code.h:1394
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
A collection of goto functions.
function_mapt function_map
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
void update()
Update all indices.
instructionst::iterator targett
instructionst::const_iterator const_targett
void compute_target_numbers()
Compute the target numbers.
const irep_idt & id() const
Definition irep.h:388
Symbol Table + CFG.
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
bool is_skip(const goto_programt &body, goto_programt::const_targett it, bool ignore_labels)
Determine whether the instruction is semantically equivalent to a skip (no-op).
Program Transformation.
code_expressiont & to_code_expression(codet &code)
Definition std_code.h:1428
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition std_types.h:29
A total order over targett and const_targett.