Skip to content

Commit 1d2e01c

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Introduce wrappers for entry location
Two kinds of user specification: either via goto location or via source line. We wrap these in entry_goto/source_locationt and build the production of the final entry_locationt.
1 parent 51e24a2 commit 1d2e01c

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

src/goto-harness/memory_snapshot_harness_generator.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Author: Daniel Poetzl
66
77
\******************************************************************/
88

9+
#include <algorithm>
10+
911
#include "memory_snapshot_harness_generator.h"
1012

1113
#include <goto-programs/goto_convert.h>
@@ -350,3 +352,133 @@ void memory_snapshot_harness_generatort::generate(
350352

351353
goto_functions.update();
352354
}
355+
356+
memory_snapshot_harness_generatort::entry_goto_locationt
357+
memory_snapshot_harness_generatort::parse_goto_location(
358+
const std::string &cmdl_option)
359+
{
360+
std::vector<std::string> start;
361+
split_string(cmdl_option, ':', start, true);
362+
363+
if(
364+
start.empty() || start.front().empty() ||
365+
(start.size() == 2 && start.back().empty()) || start.size() > 2)
366+
{
367+
throw invalid_command_line_argument_exceptiont(
368+
"invalid initial location specification", "--initial-location");
369+
}
370+
371+
if(start.size() == 2)
372+
{
373+
const auto location_number = string2optional_unsigned(start.back());
374+
CHECK_RETURN(location_number.has_value());
375+
return entry_goto_locationt{start.front(), *location_number};
376+
}
377+
else
378+
{
379+
return entry_goto_locationt{start.front()};
380+
}
381+
}
382+
383+
memory_snapshot_harness_generatort::entry_source_locationt
384+
memory_snapshot_harness_generatort::parse_source_location(
385+
const std::string &cmdl_option)
386+
{
387+
std::string initial_file_string;
388+
std::string initial_line_string;
389+
split_string(
390+
cmdl_option, ':', initial_file_string, initial_line_string, true);
391+
392+
if(initial_file_string.empty() || initial_line_string.empty())
393+
{
394+
throw invalid_command_line_argument_exceptiont(
395+
"invalid initial location specification", "--initial-file-line");
396+
}
397+
398+
const auto line_number = string2optional_unsigned(initial_line_string);
399+
CHECK_RETURN(line_number.has_value());
400+
return entry_source_locationt{initial_file_string, *line_number};
401+
}
402+
403+
memory_snapshot_harness_generatort::entry_locationt
404+
memory_snapshot_harness_generatort::initialize_entry_via_goto(
405+
const entry_goto_locationt &entry_goto_location,
406+
const goto_functionst &goto_functions)
407+
{
408+
PRECONDITION(!entry_goto_location.function_name.empty());
409+
const irep_idt &function_name = entry_goto_location.function_name;
410+
411+
// by function(+location): search for the function then jump to n-th
412+
// location, then check the number
413+
const auto &goto_function =
414+
goto_functions.function_map.find(entry_goto_location.function_name);
415+
if(
416+
goto_function != goto_functions.function_map.end() &&
417+
goto_function->second.body_available())
418+
{
419+
const auto &goto_program = goto_function->second.body;
420+
421+
const auto corresponding_instruction =
422+
entry_goto_location.find_first_corresponding_instruction(
423+
goto_program.instructions);
424+
425+
if(corresponding_instruction != goto_program.instructions.end())
426+
return entry_locationt{function_name, corresponding_instruction};
427+
}
428+
throw invalid_command_line_argument_exceptiont(
429+
"could not find the specified entry point", "--initial-goto-location");
430+
}
431+
432+
memory_snapshot_harness_generatort::entry_locationt
433+
memory_snapshot_harness_generatort::initialize_entry_via_source(
434+
const entry_source_locationt &entry_source_location,
435+
const goto_functionst &goto_functions)
436+
{
437+
PRECONDITION(!entry_source_location.file_name.empty());
438+
439+
// by line: iterate over all instructions until source location match
440+
for(const auto &entry : goto_functions.function_map)
441+
{
442+
const auto &goto_function = entry.second;
443+
// if !body_available() then body.instruction.empty() and that's fine
444+
const auto &goto_program = goto_function.body;
445+
446+
const auto corresponding_instruction =
447+
entry_source_location.find_first_corresponding_instruction(
448+
goto_program.instructions);
449+
450+
if(corresponding_instruction != goto_program.instructions.end())
451+
return entry_locationt{entry.first, corresponding_instruction};
452+
}
453+
throw invalid_command_line_argument_exceptiont(
454+
"could not find the specified entry point", "--initial-source-location");
455+
}
456+
457+
goto_programt::const_targett memory_snapshot_harness_generatort::
458+
entry_goto_locationt::find_first_corresponding_instruction(
459+
const goto_programt::instructionst &instructions) const
460+
{
461+
if(!location_number.has_value())
462+
return instructions.begin();
463+
464+
return std::find_if(
465+
instructions.begin(),
466+
instructions.end(),
467+
[this](const goto_programt::instructiont &instruction) {
468+
return *location_number == instruction.location_number;
469+
});
470+
}
471+
472+
goto_programt::const_targett memory_snapshot_harness_generatort::
473+
entry_source_locationt::find_first_corresponding_instruction(
474+
const goto_programt::instructionst &instructions) const
475+
{
476+
return std::find_if(
477+
instructions.begin(),
478+
instructions.end(),
479+
[this](const goto_programt::instructiont &instruction) {
480+
return instruction.source_location.get_file() == file_name &&
481+
safe_string2unsigned(id2string(
482+
instruction.source_location.get_line())) >= line_number;
483+
});
484+
}

src/goto-harness/memory_snapshot_harness_generator.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,103 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort
6969
override;
7070

7171
protected:
72+
/// User provided goto location: function name and (maybe) location number;
73+
/// the structure wraps this option with a parser
74+
struct entry_goto_locationt
75+
{
76+
irep_idt function_name;
77+
optionalt<unsigned> location_number;
78+
79+
entry_goto_locationt() = delete;
80+
explicit entry_goto_locationt(irep_idt function_name)
81+
: function_name(function_name)
82+
{
83+
}
84+
explicit entry_goto_locationt(
85+
irep_idt function_name,
86+
unsigned location_number)
87+
: function_name(function_name), location_number(location_number)
88+
{
89+
}
90+
91+
/// Returns the first \ref goto_programt::instructiont represented by this
92+
/// goto location, i.e. if there is no location number then the first
93+
/// instruction, otherwise the one with the right location number
94+
/// \param instructions: list of instructions to be searched
95+
/// \return iterator to the right instruction (or `end()`)
96+
goto_programt::const_targett find_first_corresponding_instruction(
97+
const goto_programt::instructionst &instructions) const;
98+
};
99+
100+
/// Parse a command line option to extract the user specified entry goto
101+
/// location
102+
/// \param cmdl_option: a string of the format <func[:<n>]>
103+
/// \return correctly constructed entry goto location
104+
entry_goto_locationt parse_goto_location(const std::string &cmdl_option);
105+
106+
/// User provided source location: file name and line number; the structure
107+
/// wraps this option with a parser
108+
struct entry_source_locationt
109+
{
110+
irep_idt file_name;
111+
unsigned line_number;
112+
113+
entry_source_locationt() = delete;
114+
explicit entry_source_locationt(irep_idt file_name, unsigned line_number)
115+
: file_name(file_name), line_number(line_number)
116+
{
117+
}
118+
119+
/// Returns the first \ref goto_programt::instructiont represented by this
120+
/// source location, i.e. one with the same file name and line number
121+
/// \param instructions: list of instructions to be searched
122+
/// \return iterator to the right instruction (or `end()`)
123+
goto_programt::const_targett find_first_corresponding_instruction(
124+
const goto_programt::instructionst &instructions) const;
125+
};
126+
127+
/// Parse a command line option to extract the user specified entry source
128+
/// location
129+
/// \param cmdl_option: a string of the format <file:n>
130+
/// \return correctly constructed entry source location
131+
entry_source_locationt parse_source_location(const std::string &cmdl_option);
132+
133+
/// Wraps the information needed to identify the entry point. Initializes via
134+
/// either \ref entry_goto_locationt or \ref entry_source_locationt
135+
struct entry_locationt
136+
{
137+
irep_idt function_name;
138+
goto_programt::const_targett start_instruction;
139+
140+
entry_locationt() = default;
141+
explicit entry_locationt(
142+
irep_idt function_name,
143+
goto_programt::const_targett start_instruction)
144+
: function_name(function_name), start_instruction(start_instruction)
145+
{
146+
}
147+
};
148+
149+
/// Find and return the entry instruction (requested by the user as goto
150+
/// location: function name + location number)
151+
/// \param entry_goto_location: user specified goto location
152+
/// \param goto_functions: goto functions to be searched for the entry
153+
/// instruction
154+
/// \return the correctly constructed entry location
155+
entry_locationt initialize_entry_via_goto(
156+
const entry_goto_locationt &entry_goto_location,
157+
const goto_functionst &goto_functions);
158+
159+
/// Find and return the entry instruction (requested by the user as source
160+
/// location: file name + line number)
161+
/// \param entry_source_location: user specified goto location
162+
/// \param goto_functions: goto functions to be searched for the entry
163+
/// instruction
164+
/// \return the correctly constructed entry location
165+
entry_locationt initialize_entry_via_source(
166+
const entry_source_locationt &entry_source_location,
167+
const goto_functionst &goto_functions);
168+
72169
/// Collect the memory-snapshot specific cmdline options (one at a time)
73170
/// \param option: memory-snapshot | initial-location | havoc-variables
74171
/// \param values: list of arguments related to a given option
@@ -155,6 +252,9 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort
155252
optionalt<unsigned> location_number;
156253
std::unordered_set<irep_idt> variables_to_havoc;
157254

255+
/// data to initialize the entry function
256+
entry_locationt entry_location;
257+
158258
message_handlert &message_handler;
159259
};
160260

0 commit comments

Comments
 (0)