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)
99 visitor.
visit_cfg(value_sets, model, no_dependencies, duplicate_body,
102 std::vector<std::size_t> subgraph_index;
106 for(std::map<event_idt, event_idt>::const_iterator
111 const std::size_t sg=subgraph_index[it->second];
119 unsigned interesting_sccs=0;
125 << interesting_sccs <<
" interesting SCCs"
136 std::size_t instr_counter=0;
137 for(goto_functionst::function_mapt::const_iterator
141 instr_counter+=it->second.body.instructions.size();
151 bool no_dependencies,
154 std::set<instrumentert::cfg_visitort::nodet> &ending_vertex)
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);
240 visit_cfg_asm_fence(i_it, function_id);
244 visit_cfg_function_call(value_sets, i_it, model,
245 no_dependencies, replicate_body);
261 #ifdef CONTEXT_INSENSITIVE
264 visit_cfg_propagate(i_it);
265 add_all_pos(it, out_nodes[function_id], in_pos[i_it]);
271 visit_cfg_propagate(i_it);
275 std::pair<unsigned, data_dpt> new_dp(thread, data_dp);
277 data_dp.print(instrumenter.message);
279 if(instrumenter.goto_functions.function_map[function_id]
280 .body.instructions.empty())
286 goto_programt::instructionst::iterator it =
287 instrumenter.goto_functions.function_map[function_id]
288 .body.instructions.end();
290 ending_vertex=in_pos[it];
295 goto_programt::instructionst::iterator i_it)
299 in_pos[i_it].
clear();
301 if(in_pos.find(in)!=in_pos.end())
302 for(
const auto &node : in_pos[in])
303 in_pos[i_it].insert(node);
319 if(instrumenter.map_function_graph.find(id_function)!=
320 instrumenter.map_function_graph.end())
325 .function_map[id_function].body.instructions;
334 goto_programt::instructionst::iterator i_it=body.end();
338 goto_programt::instructionst::iterator targ=body.begin();
340 std::set<event_idt> in_nodes;
341 std::set<event_idt> out_nodes;
344 if(in_pos.find(targ)!=in_pos.end())
347 if(updated.find(targ)!=updated.end())
350 for(std::set<nodet>::const_iterator to=in_pos[targ].begin();
351 to!=in_pos[targ].end(); ++to)
352 in_nodes.insert(to->first);
353 for(std::set<nodet>::const_iterator from=in_pos[i_it].begin();
354 from!=in_pos[i_it].end(); ++from)
355 out_nodes.insert(from->first);
359 instrumenter.message.debug() <<
"else case" <<
messaget::eom;
361 for(goto_programt::instructionst::iterator cur=i_it;
365 for(
const auto &in : cur->incoming_edges)
368 if(in_pos.find(in)!=in_pos.end() &&
369 updated.find(in)!=updated.end())
374 else if(in_pos.find(in)!=in_pos.end())
383 if(out_pos.find(targ)!=out_pos.end())
385 for(std::set<nodet>::const_iterator to=out_pos[targ].begin();
386 to!=out_pos[targ].end(); ++to)
387 in_nodes.insert(to->first);
388 for(std::set<nodet>::const_iterator from=in_pos[i_it].begin();
389 from!=in_pos[i_it].end(); ++from)
390 out_nodes.insert(from->first);
395 instrumenter.map_function_graph[id_function]=
396 std::make_pair(in_nodes, out_nodes);
419 instrumenter.message.debug()
420 <<
"contains_shared_array called for " << targ->source_location().get_line()
421 <<
" and " << i_it->source_location().get_line() <<
messaget::eom;
424 instrumenter.message.debug()
425 <<
"Do we have an array at line " << cur->source_location().get_line()
437 instrumenter.message.debug() <<
"Writes: "<<rw_set.
w_entries.size()
440 for(
const auto &r_entry : rw_set.
r_entries)
442 const irep_idt var = r_entry.second.object;
443 instrumenter.message.debug() <<
"Is "<<var<<
" an array?"
445 if(
id2string(var).find(
"[]")!=std::string::npos
446 && !instrumenter.local(var))
450 for(
const auto &w_entry : rw_set.
w_entries)
452 const irep_idt var = w_entry.second.object;
453 instrumenter.message.debug()<<
"Is "<<var<<
" an array?"<<
messaget::eom;
454 if(
id2string(var).find(
"[]")!=std::string::npos
455 && !instrumenter.local(var))
478 for(
const auto &target : i_it->targets)
481 if(in_pos.find(target)!=in_pos.end())
483 if(in_pos[i_it].empty())
486 bool duplicate_this=
false;
488 switch(replicate_body)
491 duplicate_this = contains_shared_array(
506 duplicate_this=
false;
511 visit_cfg_duplicate(goto_program, target, i_it);
513 visit_cfg_backedge(target, i_it);
523 instrumenter.message.status() <<
"Duplication..." <<
messaget::eom;
525 bool found_pos=
false;
528 if(in_pos[targ].empty())
531 for(; new_targ != goto_program.
instructions.end(); ++new_targ)
533 if(in_pos.find(new_targ)!=in_pos.end() && !in_pos[new_targ].empty())
545 new_targ->source_location().get_function() !=
546 targ->source_location().get_function() ||
547 new_targ->source_location().get_file() !=
548 targ->source_location().get_file())
553 const std::set<nodet> &up_set=in_pos[(found_pos ? new_targ : targ)];
554 const std::set<nodet> &down_set=in_pos[i_it];
556 for(std::set<nodet>::const_iterator begin_it=up_set.begin();
557 begin_it!=up_set.end(); ++begin_it)
558 instrumenter.message.debug() <<
"Up " << begin_it->first <<
messaget::eom;
560 for(std::set<nodet>::const_iterator begin_it=down_set.begin();
561 begin_it!=down_set.end(); ++begin_it)
562 instrumenter.message.debug() <<
"Down " << begin_it->first <<
messaget::eom;
564 for(std::set<nodet>::const_iterator begin_it=up_set.begin();
565 begin_it!=up_set.end(); ++begin_it)
567 for(std::set<nodet>::const_iterator end_it=down_set.begin();
568 end_it!=down_set.end(); ++end_it)
589 if(updated.find(targ)!=updated.end())
592 for(std::set<nodet>::const_iterator to=in_pos[targ].begin();
593 to!=in_pos[targ].end(); ++to)
594 for(std::set<nodet>::const_iterator from=in_pos[i_it].begin();
595 from!=in_pos[i_it].end(); ++from)
596 if(from->first!=to->first)
598 if(
egraph[from->first].thread!=
egraph[to->first].thread)
600 instrumenter.message.debug() << from->first <<
"-po->"
608 instrumenter.message.debug() <<
"else case" <<
messaget::eom;
614 for(
const auto &in : cur->incoming_edges)
616 if(in_pos.find(in)!=in_pos.end()
617 && updated.find(in)!=updated.end())
622 else if(in_pos.find(in)!=in_pos.end())
631 if(out_pos.find(targ)!=out_pos.end())
633 for(std::set<nodet>::const_iterator to=out_pos[targ].begin();
634 to!=out_pos[targ].end(); ++to)
635 for(std::set<nodet>::const_iterator from=in_pos[i_it].begin();
636 from!=in_pos[i_it].end(); ++from)
637 if(from->first!=to->first)
639 if(
egraph[from->first].thread!=
egraph[to->first].thread)
641 instrumenter.message.debug() << from->first<<
"-po->"
653 goto_programt::instructionst::iterator i_it,
665 visit_cfg_propagate(i_it);
673 instrumenter.message.debug() <<
"backward goto" <<
messaget::eom;
690 goto_programt::instructionst::iterator i_it,
692 bool no_dependencies,
702 enter_function(fun_id);
703 #ifdef CONTEXT_INSENSITIVE
704 stack_fun.push(cur_fun);
709 if(!inline_function_cond(fun_id))
713 if(instrumenter.map_function_graph.find(fun_id)!=
714 instrumenter.map_function_graph.end())
723 visit_cfg_function(value_sets, model, no_dependencies, fun_id,
725 updated.insert(i_it);
732 visit_cfg_function(value_sets, model, no_dependencies, replicate_body,
733 fun_id, in_pos[i_it]);
734 updated.insert(i_it);
737 leave_function(fun_id);
738 #ifdef CONTEXT_INSENSITIVE
739 cur_fun=stack_fun.pop();
742 catch(
const std::string &s)
744 instrumenter.message.warning() <<
"sorry, doesn't handle recursion "
745 <<
"(function " << fun_id <<
"; .cpp) "
751 goto_programt::instructionst::iterator i_it,
759 instrumenter.unique_id++,
764 egraph[new_fence_node](new_fence_event);
767 instrumenter.map_vertex_gnode.insert(
768 std::make_pair(new_fence_node, new_fence_gnode));
771 if(in_pos.find(in)!=in_pos.end())
773 for(
const auto &node : in_pos[in])
775 if(
egraph[node.first].thread!=thread)
777 instrumenter.message.debug() << node.first<<
"-po->"<<new_fence_node
784 in_pos[i_it].clear();
785 in_pos[i_it].insert(
nodet(new_fence_node, new_fence_gnode));
786 updated.insert(i_it);
790 goto_programt::instructionst::iterator i_it,
805 instrumenter.unique_id++,
817 egraph[new_fence_node](new_fence_event);
820 instrumenter.map_vertex_gnode.insert(
821 std::make_pair(new_fence_node, new_fence_gnode));
824 if(in_pos.find(in)!=in_pos.end())
826 for(
const auto &node : in_pos[in])
828 if(
egraph[node.first].thread!=thread)
830 instrumenter.message.debug() << node.first<<
"-po->"<<new_fence_node
837 in_pos[i_it].clear();
838 in_pos[i_it].insert(
nodet(new_fence_node, new_fence_gnode));
839 updated.insert(i_it);
845 goto_programt::instructionst::iterator &i_it,
867 event_idt previous=std::numeric_limits<event_idt>::max();
868 event_idt previous_gnode=std::numeric_limits<event_idt>::max();
875 if(!instruction.
labels.empty() && instruction.
labels.front()==
"ASSERT")
879 for(
const auto &r_entry : rw_set.
r_entries)
885 const irep_idt &read = r_entry.second.object;
900 instrumenter.unique_id++,
906 egraph[new_read_node]=new_read_event;
907 instrumenter.message.debug() <<
"new Read" << read <<
" @thread" << (thread)
909 << (
local(read) ?
"local" :
"shared") <<
") #"
913 unknown_read_nodes.insert(new_read_node);
917 instrumenter.map_vertex_gnode.insert(
918 std::make_pair(new_read_node, new_read_gnode));
923 if(in_pos.find(in)!=in_pos.end())
925 for(
const auto &node : in_pos[in])
927 if(
egraph[node.first].thread!=thread)
929 instrumenter.message.debug() << node.first<<
"-po->"
938 previous=new_read_node;
939 previous_gnode=new_read_gnode;
942 const std::pair<id2nodet::iterator, id2nodet::iterator>
943 with_same_var=map_writes.equal_range(read);
944 for(id2nodet::iterator id_it=with_same_var.first;
945 id_it!=with_same_var.second; id_it++)
948 instrumenter.message.debug() << id_it->second<<
"<-com->"
950 std::map<event_idt, event_idt>::const_iterator entry=
951 instrumenter.map_vertex_gnode.find(id_it->second);
952 assert(entry!=instrumenter.map_vertex_gnode.end());
961 for(std::set<event_idt>::const_iterator id_it=
962 unknown_write_nodes.begin();
963 id_it!=unknown_write_nodes.end();
967 instrumenter.message.debug() << *id_it<<
"<-com->"
969 std::map<event_idt, event_idt>::const_iterator entry=
970 instrumenter.map_vertex_gnode.find(*id_it);
971 assert(entry!=instrumenter.map_vertex_gnode.end());
981 for(
const auto &w_entry : rw_set.
w_entries)
987 const irep_idt &write = w_entry.second.object;
989 instrumenter.message.debug() <<
"WRITE: " << write <<
messaget::eom;
1003 instrumenter.unique_id++,
1009 egraph[new_write_node](new_write_event);
1011 <<
"new Write " << write <<
" @thread" << (thread) <<
"("
1013 << (
local(write) ?
"local" :
"shared") <<
") #" << new_write_node
1016 if(write==ID_unknown)
1017 unknown_read_nodes.insert(new_write_node);
1021 instrumenter.map_vertex_gnode.insert(
1022 std::pair<event_idt, event_idt>(new_write_node, new_write_gnode));
1025 if(previous!=std::numeric_limits<event_idt>::max())
1027 instrumenter.message.debug() << previous<<
"-po->"<<new_write_node
1036 if(in_pos.find(in)!=in_pos.end())
1038 for(
const auto &node : in_pos[in])
1040 if(
egraph[node.first].thread!=thread)
1042 instrumenter.message.debug() << node.first<<
"-po->"
1052 const std::pair<id2nodet::iterator, id2nodet::iterator>
1053 r_with_same_var=map_reads.equal_range(write);
1054 for(id2nodet::iterator idr_it=r_with_same_var.first;
1055 idr_it!=r_with_same_var.second; idr_it++)
1056 if(
egraph[idr_it->second].thread!=new_write_event.
thread)
1058 instrumenter.message.debug() <<idr_it->second<<
"<-com->"
1060 std::map<event_idt, event_idt>::const_iterator entry=
1061 instrumenter.map_vertex_gnode.find(idr_it->second);
1062 assert(entry!=instrumenter.map_vertex_gnode.end());
1071 const std::pair<id2nodet::iterator, id2nodet::iterator>
1072 w_with_same_var=map_writes.equal_range(write);
1073 for(id2nodet::iterator idw_it=w_with_same_var.first;
1074 idw_it!=w_with_same_var.second; idw_it++)
1075 if(
egraph[idw_it->second].thread!=new_write_event.
thread)
1077 instrumenter.message.debug() << idw_it->second<<
"<-com->"
1079 std::map<event_idt, event_idt>::const_iterator entry=
1080 instrumenter.map_vertex_gnode.find(idw_it->second);
1081 assert(entry!=instrumenter.map_vertex_gnode.end());
1090 for(std::set<event_idt>::const_iterator id_it=
1091 unknown_write_nodes.begin();
1092 id_it!=unknown_write_nodes.end();
1096 instrumenter.message.debug() << *id_it<<
"<-com->"
1098 std::map<event_idt, event_idt>::const_iterator entry=
1099 instrumenter.map_vertex_gnode.find(*id_it);
1100 assert(entry!=instrumenter.map_vertex_gnode.end());
1109 for(std::set<event_idt>::const_iterator id_it=
1110 unknown_read_nodes.begin();
1111 id_it!=unknown_read_nodes.end();
1115 instrumenter.message.debug() << *id_it<<
"<-com->"
1117 std::map<event_idt, event_idt>::const_iterator entry=
1118 instrumenter.map_vertex_gnode.find(*id_it);
1119 assert(entry!=instrumenter.map_vertex_gnode.end());
1129 previous=new_write_node;
1130 previous_gnode=new_write_gnode;
1133 if(previous!=std::numeric_limits<event_idt>::max())
1135 in_pos[i_it].clear();
1136 in_pos[i_it].insert(
nodet(previous, previous_gnode));
1137 updated.insert(i_it);
1142 visit_cfg_skip(i_it);
1146 if(!no_dependencies)
1148 for(
const auto &w_entry : rw_set.
w_entries)
1150 for(
const auto &r_entry : rw_set.
r_entries)
1152 const irep_idt &write = w_entry.second.object;
1153 const irep_idt &read = r_entry.second.object;
1154 instrumenter.message.debug() <<
"dp: Write:"<<write<<
"; Read:"<<read
1158 data_dp.dp_analysis(read_p,
local(read), write_p,
local(write));
1163 for(
const auto &r_entry : rw_set.
r_entries)
1165 for(
const auto &r_entry2 : rw_set.
r_entries)
1167 const irep_idt &read2 = r_entry2.second.object;
1168 const irep_idt &read = r_entry.second.object;
1173 data_dp.dp_analysis(read_p,
local(read), read2_p,
local(read2));
1181 goto_programt::instructionst::iterator i_it,
1189 instrumenter.unique_id++,
1194 egraph[new_fence_node](new_fence_event);
1197 instrumenter.map_vertex_gnode.insert(
1198 std::make_pair(new_fence_node, new_fence_gnode));
1201 if(in_pos.find(in)!=in_pos.end())
1203 for(
const auto &node : in_pos[in])
1205 instrumenter.message.debug() << node.first<<
"-po->"<<new_fence_node
1213 s.insert(
nodet(new_fence_node, new_fence_gnode));
1215 updated.insert(i_it);
1217 in_pos[i_it].clear();
1218 in_pos[i_it].insert(
nodet(new_fence_node, new_fence_gnode));
1219 updated.insert(i_it);
1223 goto_programt::instructionst::iterator i_it)
1225 visit_cfg_propagate(i_it);
1229 goto_programt::instructionst::iterator it,
1233 it->is_set_return_value() || it->is_throw() || it->is_catch() ||
1234 it->is_skip() || it->is_dead() || it->is_start_thread() ||
1235 it->is_end_thread())
1238 if(it->is_atomic_begin() ||
1239 it->is_atomic_end())
1245 if(it->is_function_call())
1261 e_it!=cyc.
end() && ++e_it!=cyc.
end(); ++e_it)
1270 bool thread_found=
false;
1274 for(
const auto &instruction : gf_entry.second.body.instructions)
1276 if(instruction.source_location() == current_location)
1278 current_po = &gf_entry.second.body;
1293 bool exists_n=
false;
1295 for(wmm_grapht::edgest::const_iterator edge_it=pos_cur.begin();
1296 edge_it!=pos_cur.end(); edge_it++)
1298 if(pos_next.find(edge_it->first)!=pos_next.end())
1306 if((++e_it)!=cyc.
end() || !exists_n)
1312 if(i_it->source_location() == current_location)
1315 for(goto_programt::instructionst::iterator same_loc = i_it;
1317 same_loc->source_location() == i_it->source_location();
1331 bool in_cycle=
false;
1334 if(it->source_location() == current_location)
1339 if(it->source_location() == next_location)
1352 if(instruction.is_goto())
1354 for(
const auto &t : instruction.targets)
1356 bool target_in_cycle=
false;
1362 target_in_cycle=
true;
1367 if(!target_in_cycle)
1381 map.insert(std::make_pair(
1383 std::move(one_interleaving)));
1390 bmct bmc(no_option, symbol_table, no_message);
1392 bool is_spurious=bmc.run(this_interleaving);
1406 for(std::set<event_grapht::critical_cyclet>::iterator
1412 std::set<event_grapht::critical_cyclet>::iterator next=it;
1427 for(std::set<event_grapht::critical_cyclet>::iterator it=
1433 std::set<event_grapht::critical_cyclet>::iterator next=it;
1450 const std::set<event_grapht::critical_cyclet> &set,
1453 std::ofstream &output,
1455 std::ofstream &table,
1457 bool hide_internals)
1460 std::map<unsigned, std::set<event_idt> > same_po;
1461 unsigned max_thread=0;
1465 std::map<irep_idt, std::set<event_idt> > same_file;
1468 std::map<std::string, std::string> map_id2var;
1469 std::map<std::string, std::string> map_var2id;
1471 for(std::set<event_grapht::critical_cyclet>::const_iterator it =
1472 set.begin(); it!=set.end(); it++)
1474 #ifdef PRINT_UNSAFES
1477 it->print_dot(
dot, colour++, model);
1478 ref << it->print_name(model, hide_internals) <<
'\n';
1479 output << it->print_output() <<
'\n';
1480 all << it->print_all(model, map_id2var, map_var2id, hide_internals)
1484 for(std::list<event_idt>::const_iterator it_e=it->begin();
1485 it_e!=it->end(); it_e++)
1490 same_po[ev.
thread].insert(*it_e);
1501 dot << ev.
id <<
"[label=\"\\\\lb {" << ev.
id <<
"}";
1503 dot << ev.
thread <<
"\",color=red,shape=box];\n";
1511 for(
unsigned i=0; i<=max_thread; i++)
1512 if(!same_po[i].empty())
1514 dot <<
"{rank=same; thread_" << i
1515 <<
"[shape=plaintext, label=\"thread " << i <<
"\"];";
1516 for(std::set<event_idt>::iterator it=same_po[i].begin();
1517 it!=same_po[i].end(); it++)
1526 for(std::map<
irep_idt, std::set<event_idt> >::const_iterator it=
1528 it!=same_file.end(); it++)
1531 dot <<
" label=\"" << it->first <<
"\";\n";
1532 for(std::set<event_idt>::const_iterator ev_it=it->second.begin();
1533 ev_it!=it->second.end(); ev_it++)
1535 dot <<
" " <<
egraph[*ev_it].id <<
";\n";
1542 table << std::string(80,
'-');
1543 for(std::map<std::string, std::string>::const_iterator
1544 m_it=map_id2var.begin();
1545 m_it!=map_id2var.end();
1548 table <<
"\n| " << m_it->first <<
" : " << m_it->second;
1551 table << std::string(80,
'-');
1559 std::ofstream output;
1561 std::ofstream table;
1563 dot.open(
"cycles.dot");
1564 ref.open(
"ref.txt");
1565 output.open(
"output.txt");
1566 all.open(
"all.txt");
1567 table.open(
"table.txt");
1569 dot <<
"digraph G {\n";
1570 dot <<
"nodesep=1; ranksep=1;\n";
1575 model, hide_internals);
1580 std::ofstream local_dot;
1582 local_dot.open(name.c_str());
1584 local_dot <<
"digraph G {\n";
1585 local_dot <<
"nodesep=1; ranksep=1;\n";
1587 table, model, hide_internals);
1591 dot << i <<
"[label=\"SCC " << i <<
"\",link=\"" <<
"scc_" << i;
1614 std::set<event_grapht::critical_cyclet>());
1615 for(std::vector<std::set<event_idt> >::const_iterator it=
egraph_SCCs.begin();
1621 class pthread_argumentt
1626 const std::set<event_idt> &filter;
1627 std::set<event_grapht::critical_cyclet> &cycles;
1631 const std::set<event_idt> &_filter,
1632 std::set<event_grapht::critical_cyclet> &_cycles)
1633 :instr(_instr), mem(_mem), filter(_filter), cycles(_cycles)
1639 void *collect_cycles_in_thread(
void *arg)
1642 pthread_argumentt *p_arg=
reinterpret_cast<pthread_argumentt*
>(arg);
1645 const std::set<event_idt> &filter=p_arg->filter;
1646 std::set<event_grapht::critical_cyclet> &cycles=p_arg->cycles;
1655 const unsigned number_of_sccs=
num_sccs;
1656 std::set<unsigned> interesting_SCCs;
1659 pthread_t *threads=
new pthread_t[
num_sccs+1];
1662 std::set<event_grapht::critical_cyclet>());
1664 for(std::vector<std::set<unsigned> >::const_iterator it=
egraph_SCCs.begin();
1668 interesting_SCCs.insert(scc);
1671 int rc=pthread_create(&threads[scc++], NULL,
1672 collect_cycles_in_thread, &arg);
1678 for(
unsigned i=0; i<number_of_sccs; i++)
1679 if(interesting_SCCs.find(i)!=interesting_SCCs.end())
1681 int rc=pthread_join(threads[i], NULL);