CBMC
Loading...
Searching...
No Matches
cover_basic_blocks.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Coverage Instrumentation
4
5Author: Peter Schrammel
6
7\*******************************************************************/
8
11
12#include "cover_basic_blocks.h"
13
14#include <util/message.h>
15
17 const goto_programt::const_targett &instruction,
19{
20 if(instruction->incoming_edges.size() != 1)
21 return {};
22
23 const goto_programt::targett in_t = *instruction->incoming_edges.cbegin();
24 if(
25 in_t->is_goto() && !in_t->is_backwards_goto() &&
26 in_t->condition().is_true())
27 return block_map[in_t];
28
29 return {};
30}
31
32static bool
34{
35 return a.get_file() == b.get_file() && a.get_line() == b.get_line();
36}
37
39{
40 bool next_is_target = true;
42 std::size_t current_block = 0;
43
44 forall_goto_program_instructions(it, goto_program)
45 {
46 // For the purposes of coverage blocks, multiple consecutive assume
47 // instructions with the same source location are considered to be part of
48 // the same block. Assumptions should terminate a block, as subsequent
49 // instructions may be unreachable. However check instrumentation passes
50 // may insert multiple assertions in the same program location. Therefore
51 // these are combined for reasons of readability of the coverage output.
54 !(it->is_assume() &&
56 preceding_assume->source_location(), it->source_location()));
57
58 // Is it a potential beginning of a block?
59 if(next_is_target || it->is_target() || end_of_assume_group)
60 {
62 {
64 }
65 else
66 {
67 block_infos.emplace_back();
68 block_infos.back().representative_inst = it;
69 block_infos.back().source_location = source_locationt::nil();
70 current_block = block_infos.size() - 1;
71 }
72 }
73
75 current_block < block_infos.size(), "current block number out of range");
77
79
81
82 // set representative program location to instrument
83 if(
84 !it->source_location().is_nil() &&
85 !it->source_location().get_file().empty() &&
86 !it->source_location().get_line().empty() &&
87 !it->source_location().is_built_in() &&
88 block_info.source_location.is_nil())
89 {
90 block_info.representative_inst = it; // update
91 block_info.source_location = it->source_location();
92 }
93
94 next_is_target = it->is_goto() || it->is_function_call();
95 preceding_assume = it->is_assume() ? &*it : nullptr;
96 }
97}
98
100{
101 const auto it = block_map.find(t);
102 INVARIANT(it != block_map.end(), "instruction must be part of a block");
103 return it->second;
104}
105
106std::optional<goto_programt::const_targett>
108{
109 INVARIANT(block_nr < block_infos.size(), "block number out of range");
110 return block_infos[block_nr].representative_inst;
111}
112
113const source_locationt &
115{
116 INVARIANT(block_nr < block_infos.size(), "block number out of range");
117 return block_infos[block_nr].source_location;
118}
119
120const source_linest &
122{
123 INVARIANT(block_nr < block_infos.size(), "block number out of range");
124 return block_infos[block_nr].source_lines;
125}
126
128 const irep_idt &function_id,
129 const goto_programt &goto_program,
130 message_handlert &message_handler)
131{
132 messaget msg(message_handler);
133 std::set<std::size_t> blocks_seen;
134 forall_goto_program_instructions(it, goto_program)
135 {
136 const std::size_t block_nr = block_of(it);
138
139 if(
140 blocks_seen.insert(block_nr).second &&
141 block_info.representative_inst == goto_program.instructions.end())
142 {
143 msg.warning() << "Ignoring block " << (block_nr + 1) << " location "
144 << it->location_number << " " << it->source_location()
145 << " (bytecode-index already instrumented)"
146 << messaget::eom;
147 }
148 else if(
149 block_info.representative_inst == it &&
150 block_info.source_location.is_nil())
151 {
152 msg.warning() << "Ignoring block " << (block_nr + 1) << " location "
153 << it->location_number << " " << function_id
154 << " (missing source location)" << messaget::eom;
155 }
156 // The location numbers printed here are those
157 // before the coverage instrumentation.
158 }
159}
160
161void cover_basic_blockst::output(std::ostream &out) const
162{
163 for(const auto &block_pair : block_map)
164 out << block_pair.first->source_location() << " -> " << block_pair.second
165 << '\n';
166}
167
170 const goto_programt::instructiont &instruction)
171{
172 const auto &add_location = [&](const source_locationt &location) {
173 const irep_idt &line = location.get_line();
174 if(!line.empty())
175 {
176 block.source_lines.insert(location);
177 }
178 };
179 add_location(instruction.source_location());
180 instruction.code().visit_pre([&](const exprt &expr) {
181 const auto &location = expr.source_location();
182 if(!location.get_function().empty())
183 add_location(location);
184 });
185}
186
189{
191 {
192 const auto &location = it->source_location();
193 const auto &bytecode_index = location.get_java_bytecode_index();
194 auto entry = index_to_block.emplace(bytecode_index, block_infos.size());
195 if(entry.second)
196 {
197 block_infos.push_back(it);
198 block_locations.push_back(location);
199 block_source_lines.emplace_back(location);
200 }
201 else
202 {
203 block_source_lines[entry.first->second].insert(location);
204 }
205 }
206}
207
208std::size_t
210{
211 const auto &bytecode_index = t->source_location().get_java_bytecode_index();
212 const auto it = index_to_block.find(bytecode_index);
213 INVARIANT(it != index_to_block.end(), "instruction must be part of a block");
214 return it->second;
215}
216
217std::optional<goto_programt::const_targett>
219{
221 return block_infos[block_nr];
222}
223
224const source_locationt &
230
231const source_linest &
237
238void cover_basic_blocks_javat::output(std::ostream &out) const
239{
240 for(std::size_t i = 0; i < block_locations.size(); ++i)
241 out << block_locations[i] << " -> " << i << '\n';
242}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
cover_basic_blocks_javat(const goto_programt &_goto_program)
std::vector< goto_programt::const_targett > block_infos
const source_locationt & source_location_of(std::size_t block_number) const override
std::vector< source_locationt > block_locations
void output(std::ostream &out) const override
Outputs the list of blocks.
std::size_t block_of(goto_programt::const_targett t) const override
const source_linest & source_lines_of(std::size_t block_number) const override
std::vector< source_linest > block_source_lines
std::optional< goto_programt::const_targett > instruction_of(std::size_t block_number) const override
std::unordered_map< irep_idt, std::size_t > index_to_block
void output(std::ostream &out) const override
Outputs the list of blocks.
std::optional< goto_programt::const_targett > instruction_of(std::size_t block_nr) const override
static std::optional< std::size_t > continuation_of_block(const goto_programt::const_targett &instruction, block_mapt &block_map)
If this block is a continuation of a previous block through unconditional forward gotos,...
cover_basic_blockst(const goto_programt &goto_program)
std::map< goto_programt::const_targett, std::size_t, goto_programt::target_less_than > block_mapt
std::vector< block_infot > block_infos
map block numbers to block information
void report_block_anomalies(const irep_idt &function_id, const goto_programt &goto_program, message_handlert &message_handler) override
Output warnings about ignored blocks.
const source_linest & source_lines_of(std::size_t block_nr) const override
std::size_t block_of(goto_programt::const_targett t) const override
static void add_block_lines(cover_basic_blockst::block_infot &block, const goto_programt::instructiont &instruction)
Adds the lines which instruction spans to block.
const source_locationt & source_location_of(std::size_t block_nr) const override
block_mapt block_map
map program locations to block numbers
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
bool empty() const
Definition dstring.h:89
Base class for all expressions.
Definition expr.h:56
const source_locationt & source_location() const
Definition expr.h:231
This class represents an instruction in the GOTO intermediate representation.
const goto_instruction_codet & code() const
Get the code represented by this instruction.
const source_locationt & source_location() const
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
instructionst::iterator targett
instructionst::const_iterator const_targett
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
static eomt eom
Definition message.h:289
void insert(const source_locationt &loc)
Insert a line (a source location) into the set of lines.
static const source_locationt & nil()
static bool same_source_line(const source_locationt &a, const source_locationt &b)
Basic blocks detection for Coverage Instrumentation.
#define forall_goto_program_instructions(it, program)
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
source_linest source_lines
the set of source code lines belonging to this block