Skip to content

Commit 6811238

Browse files
cover_block implementation using bytecode location
This is a specific implementation of cover block for Java. It uses the bytecode index to determine blocks and replace the use of select_unique_java_bytecode_indices.
1 parent acf9fe4 commit 6811238

File tree

4 files changed

+95
-94
lines changed

4 files changed

+95
-94
lines changed

src/goto-instrument/cover.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,33 @@ Date: May 2016
2424
/// Applies instrumenters to given goto program
2525
/// \param goto_program: the goto program
2626
/// \param instrumenters: the instrumenters
27+
/// \param mode: mode of the function to instrument (for instance ID_C or
28+
/// ID_java)
2729
/// \param message_handler: a message handler
2830
void instrument_cover_goals(
2931
goto_programt &goto_program,
3032
const cover_instrumenterst &instrumenters,
33+
const irep_idt &mode,
3134
message_handlert &message_handler)
3235
{
33-
cover_basic_blockst basic_blocks(goto_program);
34-
basic_blocks.select_unique_java_bytecode_indices(
35-
goto_program, message_handler);
36-
basic_blocks.report_block_anomalies(goto_program, message_handler);
37-
38-
instrumenters(goto_program, basic_blocks);
36+
const std::unique_ptr<cover_blocks_baset> basic_blocks =
37+
mode == ID_java ? std::unique_ptr<cover_blocks_baset>(
38+
new cover_basic_blocks_javat(goto_program))
39+
: std::unique_ptr<cover_blocks_baset>(
40+
new cover_basic_blockst(goto_program));
41+
42+
basic_blocks->report_block_anomalies(goto_program, message_handler);
43+
instrumenters(goto_program, *basic_blocks);
3944
}
4045

4146
/// Instruments goto program for a given coverage criterion
4247
/// \param symbol_table: the symbol table
4348
/// \param goto_program: the goto program
4449
/// \param criterion: the coverage criterion
4550
/// \param message_handler: a message handler
51+
/// \deprecated use instrument_cover_goals(goto_programt &goto_program,
52+
/// const cover_instrumenterst &instrumenters,
53+
/// message_handlert &message_handler, const irep_idt mode) instead
4654
void instrument_cover_goals(
4755
const symbol_tablet &symbol_table,
4856
goto_programt &goto_program,
@@ -55,7 +63,8 @@ void instrument_cover_goals(
5563
cover_instrumenterst instrumenters;
5664
instrumenters.add_from_criterion(criterion, symbol_table, goal_filters);
5765

58-
instrument_cover_goals(goto_program, instrumenters, message_handler);
66+
instrument_cover_goals(
67+
goto_program, instrumenters, ID_unknown, message_handler);
5968
}
6069

6170
/// Create and add an instrumenter based on the given criterion
@@ -257,7 +266,7 @@ static void instrument_cover_goals(
257266
if(config.function_filters(function_id, function))
258267
{
259268
instrument_cover_goals(
260-
function.body, config.cover_instrumenters, message_handler);
269+
function.body, config.cover_instrumenters, config.mode, message_handler);
261270
changed = true;
262271
}
263272

@@ -320,6 +329,7 @@ bool instrument_cover_goals(
320329

321330
Forall_goto_functions(f_it, goto_functions)
322331
{
332+
config->mode = symbol_table.lookup(f_it->first)->mode;
323333
instrument_cover_goals(
324334
*config, f_it->first, f_it->second, message_handler);
325335
}

src/goto-instrument/cover.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct cover_configt
3838
{
3939
bool keep_assertions;
4040
bool traces_must_terminate;
41+
irep_idt mode;
4142
function_filterst function_filters;
4243
goal_filterst goal_filters;
4344
cover_instrumenterst cover_instrumenters;

src/goto-instrument/cover_basic_blocks.cpp

Lines changed: 45 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -108,74 +108,6 @@ cover_basic_blockst::source_location_of(const std::size_t block_nr) const
108108
return block_infos.at(block_nr).source_location;
109109
}
110110

111-
void cover_basic_blockst::select_unique_java_bytecode_indices(
112-
const goto_programt &goto_program,
113-
message_handlert &message_handler)
114-
{
115-
messaget msg(message_handler);
116-
std::set<std::size_t> blocks_seen;
117-
std::set<irep_idt> bytecode_indices_seen;
118-
119-
forall_goto_program_instructions(it, goto_program)
120-
{
121-
const std::size_t block_nr = block_of(it);
122-
if(blocks_seen.find(block_nr) != blocks_seen.end())
123-
continue;
124-
125-
INVARIANT(block_nr < block_infos.size(), "block number out of range");
126-
block_infot &block_info = block_infos.at(block_nr);
127-
if(!block_info.representative_inst)
128-
{
129-
if(!it->source_location.get_java_bytecode_index().empty())
130-
{
131-
// search for a representative
132-
if(
133-
bytecode_indices_seen
134-
.insert(it->source_location.get_java_bytecode_index())
135-
.second)
136-
{
137-
block_info.representative_inst = it;
138-
block_info.source_location = it->source_location;
139-
update_covered_lines(block_info);
140-
blocks_seen.insert(block_nr);
141-
msg.debug() << it->function << " block " << (block_nr + 1)
142-
<< ": location " << it->location_number
143-
<< ", bytecode-index "
144-
<< it->source_location.get_java_bytecode_index()
145-
<< " selected for instrumentation." << messaget::eom;
146-
}
147-
}
148-
}
149-
else if(it == *block_info.representative_inst)
150-
{
151-
// check the existing representative
152-
if(!it->source_location.get_java_bytecode_index().empty())
153-
{
154-
if(
155-
bytecode_indices_seen
156-
.insert(it->source_location.get_java_bytecode_index())
157-
.second)
158-
{
159-
blocks_seen.insert(block_nr);
160-
}
161-
else
162-
{
163-
// clash, reset to search for a new one
164-
block_info.representative_inst = {};
165-
block_info.source_location = source_locationt::nil();
166-
msg.debug() << it->function << " block " << (block_nr + 1)
167-
<< ", location " << it->location_number
168-
<< ": bytecode-index "
169-
<< it->source_location.get_java_bytecode_index()
170-
<< " already instrumented."
171-
<< " Searching for alternative instruction"
172-
<< " to instrument." << messaget::eom;
173-
}
174-
}
175-
}
176-
}
177-
}
178-
179111
void cover_basic_blockst::report_block_anomalies(
180112
const goto_programt &goto_program,
181113
message_handlert &message_handler)
@@ -228,3 +160,48 @@ void cover_basic_blockst::update_covered_lines(block_infot &block_info)
228160
std::string covered_lines = format_number_range(line_list);
229161
block_info.source_location.set_basic_block_covered_lines(covered_lines);
230162
}
163+
164+
cover_basic_blocks_javat::cover_basic_blocks_javat(
165+
const goto_programt &_goto_program)
166+
{
167+
forall_goto_program_instructions(it, _goto_program)
168+
{
169+
const auto &location = it->source_location;
170+
const auto &bytecode_index = location.get_java_bytecode_index();
171+
if(index_to_block.emplace(bytecode_index, block_infos.size()).second)
172+
{
173+
block_infos.push_back(it);
174+
block_locations.push_back(location);
175+
block_locations.back().set_basic_block_covered_lines(location.get_line());
176+
}
177+
}
178+
}
179+
180+
std::size_t
181+
cover_basic_blocks_javat::block_of(goto_programt::const_targett t) const
182+
{
183+
const auto &bytecode_index = t->source_location.get_java_bytecode_index();
184+
const auto it = index_to_block.find(bytecode_index);
185+
INVARIANT(it != index_to_block.end(), "instruction must be part of a block");
186+
return it->second;
187+
}
188+
189+
optionalt<goto_programt::const_targett>
190+
cover_basic_blocks_javat::instruction_of(const std::size_t block_nr) const
191+
{
192+
PRECONDITION(block_nr < block_infos.size());
193+
return block_infos[block_nr];
194+
}
195+
196+
const source_locationt &
197+
cover_basic_blocks_javat::source_location_of(const std::size_t block_nr) const
198+
{
199+
PRECONDITION(block_nr < block_locations.size());
200+
return block_locations[block_nr];
201+
}
202+
203+
void cover_basic_blocks_javat::output(std::ostream &out) const
204+
{
205+
for(std::size_t i = 0; i < block_locations.size(); ++i)
206+
out << block_locations[i] << " -> " << i << '\n';
207+
}

src/goto-instrument/cover_basic_blocks.h

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,6 @@ class cover_blocks_baset
3838
virtual const source_locationt &
3939
source_location_of(std::size_t block_nr) const = 0;
4040

41-
/// Select an instruction to be instrumented for each basic block such that
42-
/// the java bytecode indices for each basic block is unique
43-
/// \param goto_program The goto program
44-
/// \param message_handler The message handler
45-
virtual void select_unique_java_bytecode_indices(
46-
const goto_programt &goto_program,
47-
message_handlert &message_handler)
48-
{
49-
}
50-
5141
/// Outputs the list of blocks
5242
virtual void output(std::ostream &out) const = 0;
5343

@@ -83,14 +73,6 @@ class cover_basic_blockst final : public cover_blocks_baset
8373
const source_locationt &
8474
source_location_of(std::size_t block_nr) const override;
8575

86-
/// Select an instruction to be instrumented for each basic block such that
87-
/// the java bytecode indices for each basic block is unique
88-
/// \param goto_program The goto program
89-
/// \param message_handler The message handler
90-
void select_unique_java_bytecode_indices(
91-
const goto_programt &goto_program,
92-
message_handlert &message_handler) override;
93-
9476
/// Output warnings about ignored blocks
9577
/// \param goto_program The goto program
9678
/// \param message_handler The message handler
@@ -134,4 +116,35 @@ class cover_basic_blockst final : public cover_blocks_baset
134116
block_mapt &block_map);
135117
};
136118

119+
class cover_basic_blocks_javat final : public cover_blocks_baset
120+
{
121+
private:
122+
// map block number to first instruction of the block
123+
std::vector<goto_programt::const_targett> block_infos;
124+
// map block number to its location
125+
std::vector<source_locationt> block_locations;
126+
// map java indexes to block indexes
127+
std::unordered_map<irep_idt, std::size_t, irep_id_hash> index_to_block;
128+
129+
public:
130+
explicit cover_basic_blocks_javat(const goto_programt &_goto_program);
131+
132+
/// \param t a goto instruction
133+
/// \return block number the given goto instruction is part of
134+
std::size_t block_of(goto_programt::const_targett t) const override;
135+
136+
/// \param block_number a block number
137+
/// \return first instruction of the given block
138+
optionalt<goto_programt::const_targett>
139+
instruction_of(std::size_t block_number) const override;
140+
141+
/// \param block_number a block number
142+
/// \return source location corresponding to the given block
143+
const source_locationt &
144+
source_location_of(std::size_t block_number) const override;
145+
146+
/// Outputs the list of blocks
147+
void output(std::ostream &out) const override;
148+
};
149+
137150
#endif // CPROVER_GOTO_INSTRUMENT_COVER_BASIC_BLOCKS_H

0 commit comments

Comments
 (0)