47 identifier==
"stdin" ||
48 identifier==
"stdout" ||
49 identifier==
"stderr" ||
50 identifier==
"sys_nerr" ||
54 const size_t pos=identifier.find(
"[]");
56 if(
pos!=std::string::npos)
59 identifier.erase(
pos);
74 catch(
const std::string &exception)
106 for(std::map<event_idt, event_idt>::const_iterator
137 for(goto_functionst::function_mapt::const_iterator
158 instrumenter.message.debug()
168 instrumenter.goto_functions.function_map[function_id]);
173 instrumenter.goto_functions.function_map[function_id].body;
181 max_thread=max_thread+1;
182 coming_from=current_thread;
183 current_thread=max_thread;
186 current_thread=coming_from;
187 thread=current_thread;
189 instrumenter.message.debug()
202 #elif defined ATOMIC_FENCE
203 visit_cfg_fence(
i_it, function_id);
206 visit_cfg_propagate(
i_it);
223 else if(
is_fence(instruction, instrumenter.ns))
225 instrumenter.message.debug() <<
"Constructing a fence" <<
messaget::eom;
226 visit_cfg_fence(
i_it, function_id);
228 else if(model!=
TSO &&
is_lwfence(instruction, instrumenter.ns))
230 visit_cfg_lwfence(
i_it, function_id);
232 else if(model==
TSO &&
is_lwfence(instruction, instrumenter.ns))
235 visit_cfg_skip(
i_it);
241 visit_cfg_asm_fence(
i_it, function_id);
245 visit_cfg_function_call(value_sets,
i_it, model,
262#ifdef CONTEXT_INSENSITIVE
265 visit_cfg_propagate(
i_it);
272 visit_cfg_propagate(
i_it);
276 std::pair<unsigned, data_dpt>
new_dp(thread, data_dp);
278 data_dp.print(instrumenter.message);
280 if(instrumenter.goto_functions.function_map[function_id]
281 .body.instructions.empty())
287 goto_programt::instructionst::iterator it =
288 instrumenter.goto_functions.function_map[function_id]
289 .body.instructions.end();
296 goto_programt::instructionst::iterator
i_it)
302 if(in_pos.find(in)!=in_pos.end())
303 for(
const auto &node : in_pos[in])
304 in_pos[
i_it].insert(node);
320 if(instrumenter.map_function_graph.find(
id_function)!=
321 instrumenter.map_function_graph.end())
335 goto_programt::instructionst::iterator
i_it=body.end();
339 goto_programt::instructionst::iterator
targ=body.begin();
345 if(in_pos.find(
targ)!=in_pos.end())
348 if(updated.find(
targ)!=updated.end())
351 for(std::set<nodet>::const_iterator to=in_pos[
targ].begin();
352 to!=in_pos[
targ].end(); ++to)
354 for(std::set<nodet>::const_iterator from=in_pos[
i_it].begin();
355 from!=in_pos[
i_it].end(); ++from)
360 instrumenter.message.debug() <<
"else case" <<
messaget::eom;
362 for(goto_programt::instructionst::iterator cur=
i_it;
366 for(
const auto &in : cur->incoming_edges)
369 if(in_pos.find(in)!=in_pos.end() &&
370 updated.find(in)!=updated.end())
375 else if(in_pos.find(in)!=in_pos.end())
384 if(out_pos.find(
targ)!=out_pos.end())
386 for(std::set<nodet>::const_iterator to=out_pos[
targ].begin();
387 to!=out_pos[
targ].end(); ++to)
389 for(std::set<nodet>::const_iterator from=in_pos[
i_it].begin();
390 from!=in_pos[
i_it].end(); ++from)
420 instrumenter.message.debug()
421 <<
"contains_shared_array called for " <<
targ->source_location().get_line()
425 instrumenter.message.debug()
426 <<
"Do we have an array at line " << cur->source_location().get_line()
438 instrumenter.message.debug() <<
"Writes: "<<
rw_set.w_entries.size()
444 instrumenter.message.debug() <<
"Is "<<var<<
" an array?"
446 if(
id2string(var).find(
"[]")!=std::string::npos
447 && !instrumenter.local(var))
454 instrumenter.message.debug()<<
"Is "<<var<<
" an array?"<<
messaget::eom;
455 if(
id2string(var).find(
"[]")!=std::string::npos
456 && !instrumenter.local(var))
479 for(
const auto &target :
i_it->targets)
482 if(in_pos.find(target)!=in_pos.end())
484 if(in_pos[
i_it].empty())
512 visit_cfg_duplicate(goto_program, target,
i_it);
514 visit_cfg_backedge(target,
i_it);
524 instrumenter.message.status() <<
"Duplication..." <<
messaget::eom;
529 if(in_pos[
targ].empty())
546 new_targ->source_location().get_function() !=
547 targ->source_location().get_function() ||
548 new_targ->source_location().get_file() !=
549 targ->source_location().get_file())
590 if(updated.find(
targ)!=updated.end())
593 for(std::set<nodet>::const_iterator to=in_pos[
targ].begin();
594 to!=in_pos[
targ].end(); ++to)
595 for(std::set<nodet>::const_iterator from=in_pos[
i_it].begin();
596 from!=in_pos[
i_it].end(); ++from)
597 if(from->first!=to->first)
599 if(
egraph[from->first].thread!=
egraph[to->first].thread)
601 instrumenter.message.debug() << from->first <<
"-po->"
609 instrumenter.message.debug() <<
"else case" <<
messaget::eom;
615 for(
const auto &in : cur->incoming_edges)
617 if(in_pos.find(in)!=in_pos.end()
618 && updated.find(in)!=updated.end())
623 else if(in_pos.find(in)!=in_pos.end())
632 if(out_pos.find(
targ)!=out_pos.end())
634 for(std::set<nodet>::const_iterator to=out_pos[
targ].begin();
635 to!=out_pos[
targ].end(); ++to)
636 for(std::set<nodet>::const_iterator from=in_pos[
i_it].begin();
637 from!=in_pos[
i_it].end(); ++from)
638 if(from->first!=to->first)
640 if(
egraph[from->first].thread!=
egraph[to->first].thread)
642 instrumenter.message.debug() << from->first<<
"-po->"
654 goto_programt::instructionst::iterator
i_it,
666 visit_cfg_propagate(
i_it);
674 instrumenter.message.debug() <<
"backward goto" <<
messaget::eom;
691 goto_programt::instructionst::iterator
i_it,
703 enter_function(fun_id);
704 #ifdef CONTEXT_INSENSITIVE
714 if(instrumenter.map_function_graph.find(fun_id)!=
715 instrumenter.map_function_graph.end())
726 updated.insert(
i_it);
734 fun_id, in_pos[
i_it]);
735 updated.insert(
i_it);
738 leave_function(fun_id);
739 #ifdef CONTEXT_INSENSITIVE
743 catch(
const std::string &s)
745 instrumenter.message.warning() <<
"sorry, doesn't handle recursion "
746 <<
"(function " << fun_id <<
"; .cpp) "
752 goto_programt::instructionst::iterator
i_it,
760 instrumenter.unique_id++,
768 instrumenter.map_vertex_gnode.insert(
772 if(in_pos.find(in)!=in_pos.end())
774 for(
const auto &node : in_pos[in])
776 if(
egraph[node.first].thread!=thread)
778 instrumenter.message.debug() << node.first<<
"-po->"<<
new_fence_node
787 updated.insert(
i_it);
791 goto_programt::instructionst::iterator
i_it,
806 instrumenter.unique_id++,
821 instrumenter.map_vertex_gnode.insert(
825 if(in_pos.find(in)!=in_pos.end())
827 for(
const auto &node : in_pos[in])
829 if(
egraph[node.first].thread!=thread)
831 instrumenter.message.debug() << node.first<<
"-po->"<<
new_fence_node
840 updated.insert(
i_it);
846 goto_programt::instructionst::iterator &
i_it,
868 event_idt previous=std::numeric_limits<event_idt>::max();
876 if(!instruction.
labels.empty() && instruction.
labels.front()==
"ASSERT")
901 instrumenter.unique_id++,
908 instrumenter.message.debug() <<
"new Read" << read <<
" @thread" << (thread)
910 << (
local(read) ?
"local" :
"shared") <<
") #"
918 instrumenter.map_vertex_gnode.insert(
924 if(in_pos.find(in)!=in_pos.end())
926 for(
const auto &node : in_pos[in])
928 if(
egraph[node.first].thread!=thread)
930 instrumenter.message.debug() << node.first<<
"-po->"
943 const std::pair<id2nodet::iterator, id2nodet::iterator>
949 instrumenter.message.debug() <<
id_it->second<<
"<-com->"
951 std::map<event_idt, event_idt>::const_iterator entry=
952 instrumenter.map_vertex_gnode.find(
id_it->second);
953 assert(entry!=instrumenter.map_vertex_gnode.end());
962 for(std::set<event_idt>::const_iterator
id_it=
963 unknown_write_nodes.begin();
964 id_it!=unknown_write_nodes.end();
968 instrumenter.message.debug() << *
id_it<<
"<-com->"
970 std::map<event_idt, event_idt>::const_iterator entry=
971 instrumenter.map_vertex_gnode.find(*
id_it);
972 assert(entry!=instrumenter.map_vertex_gnode.end());
990 instrumenter.message.debug() <<
"WRITE: " << write <<
messaget::eom;
1004 instrumenter.unique_id++,
1012 <<
"new Write " << write <<
" @thread" << (thread) <<
"("
1022 instrumenter.map_vertex_gnode.insert(
1026 if(previous!=std::numeric_limits<event_idt>::max())
1028 instrumenter.message.debug() << previous<<
"-po->"<<
new_write_node
1037 if(in_pos.find(in)!=in_pos.end())
1039 for(
const auto &node : in_pos[in])
1041 if(
egraph[node.first].thread!=thread)
1043 instrumenter.message.debug() << node.first<<
"-po->"
1053 const std::pair<id2nodet::iterator, id2nodet::iterator>
1059 instrumenter.message.debug() <<
idr_it->second<<
"<-com->"
1061 std::map<event_idt, event_idt>::const_iterator entry=
1062 instrumenter.map_vertex_gnode.find(
idr_it->second);
1063 assert(entry!=instrumenter.map_vertex_gnode.end());
1072 const std::pair<id2nodet::iterator, id2nodet::iterator>
1078 instrumenter.message.debug() <<
idw_it->second<<
"<-com->"
1080 std::map<event_idt, event_idt>::const_iterator entry=
1081 instrumenter.map_vertex_gnode.find(
idw_it->second);
1082 assert(entry!=instrumenter.map_vertex_gnode.end());
1091 for(std::set<event_idt>::const_iterator
id_it=
1092 unknown_write_nodes.begin();
1093 id_it!=unknown_write_nodes.end();
1097 instrumenter.message.debug() << *
id_it<<
"<-com->"
1099 std::map<event_idt, event_idt>::const_iterator entry=
1100 instrumenter.map_vertex_gnode.find(*
id_it);
1101 assert(entry!=instrumenter.map_vertex_gnode.end());
1110 for(std::set<event_idt>::const_iterator
id_it=
1111 unknown_read_nodes.begin();
1112 id_it!=unknown_read_nodes.end();
1116 instrumenter.message.debug() << *
id_it<<
"<-com->"
1118 std::map<event_idt, event_idt>::const_iterator entry=
1119 instrumenter.map_vertex_gnode.find(*
id_it);
1120 assert(entry!=instrumenter.map_vertex_gnode.end());
1134 if(previous!=std::numeric_limits<event_idt>::max())
1138 updated.insert(
i_it);
1143 visit_cfg_skip(
i_it);
1155 instrumenter.message.debug() <<
"dp: Write:"<<write<<
"; Read:"<<read
1182 goto_programt::instructionst::iterator
i_it,
1190 instrumenter.unique_id++,
1198 instrumenter.map_vertex_gnode.insert(
1202 if(in_pos.find(in)!=in_pos.end())
1204 for(
const auto &node : in_pos[in])
1206 instrumenter.message.debug() << node.first<<
"-po->"<<
new_fence_node
1216 updated.insert(
i_it);
1220 updated.insert(
i_it);
1224 goto_programt::instructionst::iterator
i_it)
1226 visit_cfg_propagate(
i_it);
1230 goto_programt::instructionst::iterator it,
1234 it->is_set_return_value() || it->is_throw() || it->is_catch() ||
1235 it->is_skip() || it->is_dead() || it->is_start_thread() ||
1236 it->is_end_thread())
1239 if(it->is_atomic_begin() ||
1240 it->is_atomic_end())
1246 if(it->is_function_call())
1275 for(
const auto &instruction :
gf_entry.second.body.instructions)
1277 if(instruction.source_location() == current_location)
1313 if(
i_it->source_location() == current_location)
1316 for(goto_programt::instructionst::iterator
same_loc =
i_it;
1318 same_loc->source_location() ==
i_it->source_location();
1335 if(it->source_location() == current_location)
1353 if(instruction.is_goto())
1355 for(
const auto &t : instruction.targets)
1382 map.insert(std::make_pair(
1408 for(std::set<event_grapht::critical_cyclet>::iterator
1414 std::set<event_grapht::critical_cyclet>::iterator next=it;
1429 for(std::set<event_grapht::critical_cyclet>::iterator it=
1435 std::set<event_grapht::critical_cyclet>::iterator next=it;
1452 const std::set<event_grapht::critical_cyclet> &set,
1455 std::ofstream &output,
1457 std::ofstream &
table,
1459 bool hide_internals)
1462 std::map<unsigned, std::set<event_idt> >
same_po;
1463 unsigned max_thread=0;
1467 std::map<irep_idt, std::set<event_idt> >
same_file;
1470 std::map<std::string, std::string>
map_id2var;
1471 std::map<std::string, std::string>
map_var2id;
1473 for(std::set<event_grapht::critical_cyclet>::const_iterator it =
1474 set.begin(); it!=set.end(); it++)
1480 ref << it->print_name(model, hide_internals) <<
'\n';
1481 output << it->print_output() <<
'\n';
1486 for(std::list<event_idt>::const_iterator
it_e=it->begin();
1497 if(
ev.thread>max_thread)
1498 max_thread=
ev.thread;
1503 dot <<
ev.id <<
"[label=\"\\\\lb {" <<
ev.id <<
"}";
1504 dot <<
ev.get_operation() <<
"{" <<
ev.variable <<
"} {} @thread";
1505 dot <<
ev.thread <<
"\",color=red,shape=box];\n";
1513 for(
unsigned i=0;
i<=max_thread;
i++)
1516 dot <<
"{rank=same; thread_" <<
i
1517 <<
"[shape=plaintext, label=\"thread " <<
i <<
"\"];";
1518 for(std::set<event_idt>::iterator it=
same_po[
i].begin();
1528 for(std::map<
irep_idt, std::set<event_idt> >::const_iterator it=
1533 dot <<
" label=\"" << it->first <<
"\";\n";
1534 for(std::set<event_idt>::const_iterator
ev_it=it->second.begin();
1544 table << std::string(80,
'-');
1545 for(std::map<std::string, std::string>::const_iterator
1553 table << std::string(80,
'-');
1561 std::ofstream output;
1563 std::ofstream
table;
1565 dot.open(
"cycles.dot");
1566 ref.open(
"ref.txt");
1567 output.open(
"output.txt");
1568 all.open(
"all.txt");
1569 table.open(
"table.txt");
1571 dot <<
"digraph G {\n";
1572 dot <<
"nodesep=1; ranksep=1;\n";
1577 model, hide_internals);
1583 std::string name=
"scc_" + std::to_string(
i) +
".dot";
1589 table, model, hide_internals);
1593 dot <<
i <<
"[label=\"SCC " <<
i <<
"\",link=\"" <<
"scc_" <<
i;
1616 std::set<event_grapht::critical_cyclet>());
1617 for(std::vector<std::set<event_idt> >::const_iterator it=
egraph_SCCs.begin();
1628 const std::set<event_idt> &filter;
1629 std::set<event_grapht::critical_cyclet> &cycles;
1633 const std::set<event_idt> &
_filter,
1634 std::set<event_grapht::critical_cyclet> &
_cycles)
1647 const std::set<event_idt> &filter=
p_arg->filter;
1648 std::set<event_grapht::critical_cyclet> &cycles=
p_arg->cycles;
1664 std::set<event_grapht::critical_cyclet>());
1666 for(std::vector<std::set<unsigned> >::const_iterator it=
egraph_SCCs.begin();
virtual void clear()
Reset the abstract state.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
const irep_idt & get_statement() const
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
data_typet::const_iterator const_iterator
event_idt copy_segment(event_idt begin, event_idt end)
const wmm_grapht::edgest & po_out(event_idt n) const
void collect_cycles(std::set< critical_cyclet > &set_of_cycles, memory_modelt model, const std::set< event_idt > &filter)
std::map< unsigned, data_dpt > map_data_dp
void add_com_edge(event_idt a, event_idt b)
void add_po_edge(event_idt a, event_idt b)
void add_po_back_edge(event_idt a, event_idt b)
Base class for all expressions.
const source_locationt & source_location() const
The Boolean constant false.
A collection of goto functions.
std::map< irep_idt, goto_functiont > function_mapt
function_mapt function_map
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
This class represents an instruction in the GOTO intermediate representation.
bool is_set_return_value() const
std::set< targett > incoming_edges
const codet & get_code() const
Get the code represented by this instruction.
bool is_end_thread() const
bool is_start_thread() const
bool is_atomic_end() const
bool is_backwards_goto() const
Returns true if the instruction is a backwards branch.
const exprt & call_function() const
Get the function that is called for FUNCTION_CALL.
bool is_atomic_begin() const
bool is_function_call() const
const source_locationt & source_location() const
goto_program_instruction_typet type() const
What kind of instruction?
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
instructionst::const_iterator const_targett
std::list< instructiont > instructionst
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
std::size_t SCCs(std::vector< node_indext > &subgraph_nr) const
Computes strongly-connected components of a graph and yields a vector expressing a mapping from nodes...
node_indext add_node(arguments &&... values)
void add_edge(node_indext a, node_indext b)
void visit_cfg_backedge(goto_programt::const_targett targ, goto_programt::const_targett i_it)
strategy: fwd/bwd alternation
void visit_cfg_reference_function(irep_idt id_function)
references the first and last edges of the function
bool contains_shared_array(const irep_idt &function_id, goto_programt::const_targett targ, goto_programt::const_targett i_it, value_setst &value_sets) const
instrumentert & instrumenter
virtual void visit_cfg_function(value_setst &value_sets, memory_modelt model, bool no_dependencies, loop_strategyt duplicate_body, const irep_idt &function_id, std::set< nodet > &ending_vertex)
TODO: move the visitor outside, and inherit.
std::pair< irep_idt, event_idt > id2node_pairt
bool local(const irep_idt &i)
void visit_cfg_fence(goto_programt::instructionst::iterator i_it, const irep_idt &function_id)
void visit_cfg_goto(const irep_idt &function_id, const goto_programt &goto_program, goto_programt::instructionst::iterator i_it, loop_strategyt replicate_body, value_setst &value_sets)
void visit_cfg_function_call(value_setst &value_sets, goto_programt::instructionst::iterator i_it, memory_modelt model, bool no_dependenciess, loop_strategyt duplicate_body)
void visit_cfg_lwfence(goto_programt::instructionst::iterator i_it, const irep_idt &function_id)
void visit_cfg_propagate(goto_programt::instructionst::iterator i_it)
void visit_cfg_assign(value_setst &value_sets, const irep_idt &function_id, goto_programt::instructionst::iterator &i_it, bool no_dependencies)
void visit_cfg_duplicate(const goto_programt &goto_program, goto_programt::const_targett targ, goto_programt::const_targett i_it)
void visit_cfg_body(const irep_idt &function_id, const goto_programt &goto_program, goto_programt::const_targett i_it, loop_strategyt replicate_body, value_setst &value_sets)
strategy: fwd/bwd alternation
std::pair< event_idt, event_idt > nodet
void visit_cfg_thread() const
void visit_cfg_skip(goto_programt::instructionst::iterator i_it)
void visit_cfg_asm_fence(goto_programt::instructionst::iterator i_it, const irep_idt &function_id)
void print_outputs(memory_modelt model, bool hide_internals)
void collect_cycles_by_SCCs(memory_modelt model)
Note: can be distributed (#define DISTRIBUTED)
std::set< event_grapht::critical_cyclet > set_of_cycles
std::set< irep_idt > var_to_instr
std::vector< std::set< event_idt > > egraph_SCCs
std::multimap< irep_idt, source_locationt > id2loc
bool is_cfg_spurious(const event_grapht::critical_cyclet &cyc)
goto_functionst & goto_functions
std::map< event_idt, event_idt > map_vertex_gnode
std::vector< std::set< event_grapht::critical_cyclet > > set_of_cycles_per_SCC
void add_instr_to_interleaving(goto_programt::instructionst::iterator it, goto_programt &interleaving)
bool local(const irep_idt &id)
is local variable?
unsigned goto2graph_cfg(value_setst &value_sets, memory_modelt model, bool no_dependencies, loop_strategyt duplicate_body)
goes through CFG and build a static abstract event graph overapproximating the read/write relations f...
void print_outputs_local(const std::set< event_grapht::critical_cyclet > &set, std::ofstream &dot, std::ofstream &ref, std::ofstream &output, std::ofstream &all, std::ofstream &table, memory_modelt model, bool hide_internals)
bool get_bool(const irep_idt &name) const
mstreamt & statistics() const
mstreamt & status() const
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
const irep_idt & get_identifier() const
bool has_prefix(const std::string &s, const std::string &prefix)
void dot(const goto_modelt &src, std::ostream &out)
wmm_grapht::node_indext event_idt
bool is_fence(const goto_programt::instructiont &instruction, const namespacet &ns)
bool is_lwfence(const goto_programt::instructiont &instruction, const namespacet &ns)
Fences for instrumentation.
event_idt alt_copy_segment(wmm_grapht &alt_egraph, event_idt begin, event_idt end)
#define add_all_pos(it, target, source)
#define forall_goto_program_instructions(it, program)
#define Forall_goto_program_instructions(it, program)
dstring_hash irep_id_hash
const std::string & id2string(const irep_idt &d)
Race Detection for Threaded Goto Programs.
#define INITIALIZE_FUNCTION
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.