29 : split_block_{block}, false_idx_{0}, path_idx_{0} {}
56 : split_block_{block},
57 cfg_block_{block->getCFGBlock()} {
78 str += std::to_string(block->getBlockID());
91 str += std::to_string(block->getBlockID());
104 llvm::dbgs() <<
"T ";
106 llvm::dbgs() << block->getBlockID() <<
" ";
108 llvm::dbgs() <<
"; F ";
110 llvm::dbgs() << block->getBlockID() <<
" ";
118 for (
auto const& path_pair : from) {
129 llvm::SmallPtrSet<const SplitCFGBlock*, 32>& visited_blocks,
130 llvm::SmallVectorImpl<const SplitCFGBlock*>& waits_to_visit,
131 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& visited_waits,
132 llvm::SmallVector<SplitCFGPathPair>& curr_path) {
133 bool true_path_{
false};
134 bool false_path_{
false};
135 bool stop_local_path{
false};
146 std::pair<const SplitCFGBlock*, SplitCFGBlock::const_succ_iterator>, 8>
149 visited_blocks.insert(BB);
150 to_visit.push_back(std::make_pair(BB, BB->
succ_begin()));
154 std::pair<const SplitCFGBlock*, SplitCFGBlock::const_succ_iterator>& Top =
160 bool bb_has_wait{(ParentBB->hasWait())};
166 llvm::dbgs() <<
"Visit Parent BB# " << ParentBB->getBlockID() <<
" ; ";
169 curr_path.push_back(std::make_pair(ParentBB, info));
170 id = curr_path.size() - 1;
172 if (!stop_local_path) {
173 local_path.push_back(
182 llvm::dbgs() <<
" has WAIT ";
185 if (visited_waits.insert(ParentBB).second) {
186 waits_to_visit.insert(waits_to_visit.begin(), BB);
198 llvm::SmallPtrSet<const SplitCFGBlock*, 32> save_visited_blocks{
204 llvm::dbgs() <<
"Found successor BB " << BB->
getBlockID()
205 <<
" for parentBB " << ParentBB->getBlockID() <<
"\n";
214 llvm::dbgs() <<
"\n#### ParentBB " << ParentBB->getBlockID()
215 <<
" is a loop with 2 succ or conditional. Succ BB# "
223 if (
const auto true_block_succ = *ParentBB->succ_begin()) {
224 if (true_block_succ == BB) {
226 llvm::dbgs() <<
"Going down the TRUE path for BB"
227 << block_path->first->getBlockID() <<
" \n";
231 llvm::dbgs() <<
"Going down the FALSE path for BB"
232 << block_path->first->getBlockID() <<
" \n";
237 llvm::SmallPtrSet<const SplitCFGBlock*, 32> loop_visited_blocks{
238 save_visited_blocks};
245 loop_visited_blocks.insert(ParentBB);
247 llvm::dbgs() <<
"\n==============================================";
248 llvm::dbgs() <<
"\n[START] Recursive DFS starting at BB "
250 << ParentBB->getBlockID() <<
" T " << true_path_ <<
" F "
251 << false_path_ <<
"\n";
252 llvm::dbgs() <<
"loop visited ";
254 llvm::dbgs() <<
"visited ";
256 llvm::dbgs() <<
"local_path : ";
258 llvm::dbgs() <<
"\n";
263 BB, loop_visited_blocks, waits_to_visit, visited_waits, curr_path);
264 llvm::dbgs() <<
"\n";
272 llvm::dbgs() <<
"[AFTER] DFS for BB# " << BB->
getBlockID()
273 <<
" for parent BB# " << ParentBB->getBlockID() <<
" T "
274 << true_path_ <<
" F " << false_path_ <<
"\n";
275 llvm::dbgs() <<
"loop visited ";
277 llvm::dbgs() <<
"visited ";
279 llvm::dbgs() <<
"sub_path : ";
282 llvm::dbgs() <<
"\n[END] Recurse DFS at BB " << BB->
getBlockID()
283 <<
" parent BB# " << ParentBB->getBlockID() <<
" T "
284 << true_path_ <<
" F " << false_path_ <<
"\n";
294 llvm::dbgs() <<
"[TRUE PATH] Set path for BB "
295 << ParentBB->getBlockID() <<
" to sub_path ";
297 llvm::dbgs() <<
"\n";
300 auto& info{curr_path[id]};
302 llvm::dbgs() <<
"curr_path :";
304 info.second.false_idx_ = curr_path.size();
312 const clang::CFGBlock* cblock{ParentBB->getCFGBlock()};
313 const clang::CFGBlock* fsucc{*cblock->succ_rbegin()};
319 for (
auto const visited_blk : curr_path) {
320 if (visited_blk.first->getCFGBlock() == fsucc) {
321 info.second.false_idx_ = visited_blk.second.path_idx_;
331 }
else if (false_path_) {
333 llvm::dbgs() <<
"[FALSE PATH] Set path for BB "
334 << ParentBB->getBlockID() <<
" to sub_path ";
336 llvm::dbgs() <<
"\n";
345 llvm::dbgs() <<
"\n==============================================";
358 llvm::dbgs() <<
"\nNO SUCCESOR for BB " << ParentBB->getBlockID()
367 }
while (found_succ);
369 llvm::dbgs() <<
"@@@@@@ Exiting loop\n";
381 }
while (!to_visit.empty());
388 if (block_path !=
path_info_.end() && !block_path->second.isTruePathValid()) {
390 for (
const auto block : newly_visited) {
391 block_path->second.true_path_.push_back(block.first);
400 !block_path->second.isFalsePathValid()) {
401 for (
const auto block : newly_visited) {
402 block_path->second.false_path_.push_back(block.first);
403 llvm::dbgs() <<
"=> " << block.first->getBlockID() <<
" ";
409 const llvm::SmallPtrSetImpl<const SplitCFGBlock*>& larger,
410 const llvm::SmallPtrSetImpl<const SplitCFGBlock*>& smaller,
411 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& to) {
412 for (
const auto& element : larger) {
413 if (!smaller.contains(element)) {
421 if (!parent_block || !block) {
425 return (*parent_block->
succ_begin() == block);
429 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& visited) {
430 llvm::dbgs() <<
" : ";
431 for (
const auto sblock : visited) {
432 llvm::dbgs() << sblock->getBlockID() <<
" ";
434 llvm::dbgs() <<
"\n";
438 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& to,
439 const llvm::SmallPtrSetImpl<const SplitCFGBlock*>& from) {
440 for (
const auto sblock : from) {
457 std::pair<const SplitCFGBlock*, SplitCFGBlock::const_succ_iterator>, 8>&
460 if ((found) && (parent_has_wait ==
false)) {
462 to_visit.push_back(std::make_pair(BB, BB->
succ_begin()));
474 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& visited_blocks,
477 while (I != curr_block->
succ_end()) {
479 if ((block !=
nullptr) && (visited_blocks.insert(block).second)) {
491 if (block ==
nullptr) {
499 if (block ==
nullptr) {
502 auto stmt{block->
getCFGBlock()->getTerminatorStmt()};
503 return stmt && clang::dyn_cast<clang::ConditionalOperator>(stmt);
510 if (block ==
nullptr) {
514 auto stmt{block->
getCFGBlock()->getTerminatorStmt()};
516 (llvm::isa<clang::WhileStmt>(stmt) ||
517 llvm::isa<clang::ForStmt>(stmt) || llvm::isa<clang::DoStmt>(stmt));
523 llvm::SmallPtrSet<const SplitCFGBlock*, 32> visited_waits;
525 const clang::CFGBlock* block{&
cfg_->getEntry()};
527 llvm::SmallPtrSet<const SplitCFGBlock*, 32> visited_blocks;
534 <<
"##############################################################\n";
535 llvm::dbgs() <<
"@@@@@ DFS call for SB " << entry->
getBlockID() <<
"\n";
539 std::unordered_map<const SplitCFGBlock*, SplitCFGPathInfo>
542 dfs_visit_wait(entry, visited_blocks, waits_to_visit, visited_waits,
544 paths_.push_back(curr_path);
545 llvm::dbgs() <<
"curr path 1 below\n";
552 while (!waits_to_visit.empty()) {
554 visited_blocks.clear();
556 entry = waits_to_visit.pop_back_val();
558 <<
"##############################################################\n";
560 llvm::dbgs() <<
"\n@@@@@ DFS call for SB " << entry->getBlockID() <<
"\n";
562 dfs_visit_wait(entry, visited_blocks, waits_to_visit, visited_waits,
564 paths_.push_back(curr_path);
565 llvm::dbgs() <<
"curr path 2 below\n";
584 if (
auto cfg_stmt = element.getAs<clang::CFGStmt>()) {
585 auto stmt{cfg_stmt->getStmt()};
587 if (
auto* expr = llvm::dyn_cast<clang::Expr>(stmt)) {
588 if (
auto cxx_me = llvm::dyn_cast<clang::CXXMemberCallExpr>(expr)) {
589 auto args{cxx_me->getNumArgs()};
591 if (
auto first_arg{cxx_me->getArg(0)}) {
592 llvm::dbgs() <<
"*************** FIRST ARG ****************\n";
598 if (first_arg->isEvaluatable(
context_)) {
599 clang::Expr::EvalResult result{};
600 first_arg->EvaluateAsInt(result,
context_);
601 llvm::dbgs() <<
" ARG VAL: ";
603 return result.Val.getInt();
611 return llvm::APInt{32, 0,
false};
615 if (
auto cfg_stmt = element.getAs<clang::CFGStmt>()) {
616 auto stmt{cfg_stmt->getStmt()};
619 if (
auto* expr = llvm::dyn_cast<clang::Expr>(stmt)) {
621 if (
auto cxx_me = llvm::dyn_cast<clang::CallExpr>(expr)) {
622 if (
auto direct_callee = cxx_me->getDirectCallee()) {
623 auto name{direct_callee->getNameInfo().getAsString()};
624 if (name == std::string(
"wait")) {
626 auto args{cxx_me->getNumArgs()};
628 llvm::errs() <<
"wait() must have either 0 or 1 argument.\n";
643 assert(block !=
nullptr);
645 unsigned int num_elements{block->size()};
647 llvm::dbgs() <<
"\n\nChecking if block " << block->getBlockID()
648 <<
" has a wait()\n";
649 llvm::dbgs() <<
"Number of elements " << num_elements <<
"\n";
656 llvm::SmallVector<std::pair<VectorCFGElementPtr, bool>>
split_elements;
659 if (num_elements == 0) {
662 bool has_wait{
false};
663 for (
auto const& element : block->refs()) {
665 llvm::dbgs() <<
"Is this a wait? ";
671 const clang::CFGElement* element_ptr{element.operator->()};
674 llvm::dbgs() <<
" IT IS A WAIT\n";
676 if (num_elements == 1) {
677 llvm::dbgs() <<
"DBG: Only one statement and it is a wait().\n";
681 if (vec_elements.size() != 0) {
683 vec_elements.clear();
687 vec_elements.push_back(element_ptr);
689 vec_elements.clear();
693 vec_elements.push_back(element_ptr);
697 if (vec_elements.size() != 0) {
706 clang::CFGBlock* block,
707 const llvm::SmallVectorImpl<std::pair<SplitCFG::VectorCFGElementPtr, bool>>&
711 llvm::dbgs() <<
"Number of entries in split_elements "
717 llvm::dbgs() <<
"Element number " <<
id <<
" ";
721 bool already_exists{
false};
724 auto scit{
sccfg_.find(block->getBlockID())};
727 new_split = scit->second;
728 new_split->id_ = block->getBlockID();
738 auto scit{
sccfg_.find(block->getBlockID())};
740 new_split->
id_ = block->getBlockID() * 10 + id;
742 auto is_wait = elements.second;
743 auto stmt{block->getTerminatorStmt()};
745 new_split->is_conditional_ =
746 !is_wait && (stmt && (llvm::isa<clang::IfStmt>(stmt) ||
747 llvm::isa<clang::ConditionalOperator>(stmt)));
752 llvm::dbgs() <<
"SB# " << new_split->id_ <<
" size "
755 llvm::dbgs() <<
" add successors of BB# " << block->getBlockID()
759 prev_block->successors_.push_back(new_split);
761 new_split->predecessors_.push_back(prev_block);
762 sccfg_.insert(std::make_pair(block->getBlockID() * 10 +
id, new_split));
765 new_split->
block_ = block;
766 new_split->has_wait_ = elements.second;
767 new_split->elements_ = elements.first;
770 if (new_split->has_wait_) {
772 const clang::CFGElement* wait_el = (*new_split->elements_.begin());
780 new_split->identifyBreaks(
context_);
783 prev_block = new_split;
789 for (
auto const& succ : from->succs()) {
791 auto fit{
sccfg_.find(succ->getBlockID())};
799 for (
auto const& pre : from->preds()) {
801 auto fit{
sccfg_.find(pre->getBlockID())};
809 llvm::dbgs() <<
"sccfg( " <<
sccfg_.size() <<
") ids: ";
810 for (
auto const& entry :
sccfg_) {
811 llvm::dbgs() << entry.first <<
" ";
813 llvm::dbgs() <<
"\n";
817 const llvm::SmallVector<std::pair<VectorCFGElementPtr, bool>>&
818 split_elements)
const {
821 llvm::dbgs() <<
"Element number " <<
id <<
" has " << elements.first.size()
822 <<
" items and has ";
823 if (elements.second) {
824 llvm::dbgs() <<
" a WAIT\n";
826 llvm::dbgs() <<
" NO WAIT\n";
828 for (
auto const& element : elements.first) {
841 auto next_block{wait.second.first};
842 auto next_state_id{wait.second.second};
849 llvm::dbgs() <<
"Dump all wait next states\n";
851 auto wait_block{wait.first};
852 auto next_block{wait.second.first};
853 auto next_state_id{wait.second.second};
855 llvm::dbgs() <<
"SB" << wait_block->getBlockID() <<
" (SB"
856 << next_block->getBlockID() <<
")"
857 <<
" [S" << next_state_id <<
"]\n";
864 llvm::dbgs() <<
"Dump curr SB path to wait() found in the CFG.\n";
866 for (
auto const& block : curr_path) {
867 auto sblock{block.first};
868 llvm::dbgs() << sblock->getBlockID() <<
" ";
872 auto next_state{wit->second.second};
873 llvm::dbgs() <<
"[S" << next_state <<
"] ";
876 llvm::dbgs() <<
"\n";
880 llvm::dbgs() <<
"#### Dump all SB paths to wait() found in the CFG.\n";
883 for (
auto const& block_vector :
paths_) {
884 llvm::dbgs() <<
"Path S" << i++ <<
": ";
885 for (
auto const& block : block_vector) {
886 auto sblock{block.first};
887 auto supp_info{block.second};
888 auto found_it{
path_info_.find(supp_info.split_block_)};
895 llvm::dbgs() <<
"(" << supp_info.path_idx_ <<
"," << sblock->getBlockID()
896 <<
"," << supp_info.false_idx_;
898 llvm::dbgs() <<
" |" << found_it->second.getFalsePath().size() <<
"|";
899 if (found_it->second.getFalsePath().size() > 0) {
900 found_it->second.dump();
903 llvm::dbgs() <<
") ";
907 auto next_state{wit->second.second};
908 llvm::dbgs() <<
"[S" << next_state <<
"] ";
912 llvm::dbgs() <<
" (reset path)";
915 llvm::dbgs() <<
"\n";
920 llvm::dbgs() <<
"Dump [ALL] path info\n";
924 llvm::dbgs() <<
"S" << i <<
" : \n";
925 for (
const auto& path_pair : path) {
926 auto sblock{path_pair.first};
927 auto sinfo{path_pair.second};
930 llvm::dbgs() <<
"\n";
937 llvm::dbgs() <<
"Dump all path info\n";
940 auto sblock{path_pair.first};
941 auto sinfo{path_pair.second};
944 llvm::dbgs() <<
"\n";
949 for (
auto begin_it =
cfg_->nodes_begin(); begin_it !=
cfg_->nodes_end();
951 auto block{*begin_it};
953 new_block->
id_ = block->getBlockID();
956 auto stmt{block->getTerminatorStmt()};
957 new_block->is_conditional_ =
958 stmt && (llvm::isa<clang::IfStmt>(stmt) ||
959 llvm::isa<clang::ConditionalOperator>(stmt));
961 bool last_succ_is_null{
false};
962 if (block->succ_size() == 2) {
964 if (*block->succ_rbegin() ==
nullptr) {
965 last_succ_is_null =
true;
970 bool is_loop{stmt && (llvm::isa<clang::WhileStmt>(stmt) ||
971 llvm::isa<clang::ForStmt>(stmt) ||
972 llvm::isa<clang::DoStmt>(stmt))};
974 new_block->is_loop_with_two_succ_ =
975 (stmt && is_loop && (last_succ_is_null ==
false));
977 sccfg_.insert(std::make_pair(new_block->id_, new_block));
980 llvm::dbgs() <<
"sccfg( " <<
sccfg_.size() <<
") ids: ";
981 for (
auto const& entry :
sccfg_) {
982 llvm::dbgs() << entry.first <<
" ";
984 llvm::dbgs() <<
"\n";
988 cfg_ = clang::CFG::buildCFG(method, method->getBody(), &
context_,
989 clang::CFG::BuildOptions());
991 clang::LangOptions lang_opts;
992 cfg_->dump(lang_opts,
true);
996 for (
auto begin_it =
cfg_->nodes_begin(); begin_it !=
cfg_->nodes_end();
998 auto block{*begin_it};
1001 auto stmt{block->getTerminatorStmt()};
1002 if (stmt && clang::dyn_cast<clang::ConditionalOperator>(stmt)) {
1016 llvm::dbgs() <<
"\nPrepare to update successors\n";
1021 for (
auto& block :
sccfg_) {
1030 for (
auto block :
sccfg_) {
1032 delete block.second;
1038 llvm::dbgs() <<
"Dump all nodes in SCCFG\n";
1039 for (
auto const& block :
sccfg_) {
1049 std::error_code OutErrorInfo;
1051 llvm::raw_fd_ostream dotos(llvm::StringRef(
"sccfg.dot"), OutErrorInfo,
1052 llvm::sys::fs::OF_None);
1054 dotos <<
"digraph SCCFG {\n";
1055 dotos <<
" rankdir=TD\n";
1056 dotos <<
" node [shape=record]\n";
1058 for (
auto const& block :
sccfg_) {
1062 std::string element_str{};
1063 llvm::raw_string_ostream element_os(element_str);
1064 auto num_elements{sblock->getElements().size()};
1068 for (
auto const& element : sblock->getElements()) {
1069 element_os <<
"| " << i <<
":";
1070 element->dumpToStream(element_os);
1078 std::regex re(
"\\-");
1079 element_str = std::regex_replace(element_str, re,
"\\-");
1080 std::regex replus(
"\\+");
1081 element_str = std::regex_replace(element_str, replus,
"\\+");
1082 std::regex relt(
"\\<");
1083 element_str = std::regex_replace(element_str, relt,
"\\<");
1084 std::regex regt(
"\\>");
1085 element_str = std::regex_replace(element_str, regt,
"\\>");
1086 std::regex reamp(
"\\&");
1087 element_str = std::regex_replace(element_str, reamp,
"\\&");
1089 if (sblock->hasWait()) {
1090 dotos <<
"SB" << sblock->getBlockID() <<
" [ \n color=red, label=\"SB"
1091 << sblock->getBlockID() <<
"\n"
1092 <<
" [" << sblock->getNextState() <<
"] | WAIT " << element_str
1097 element_str +=
" | TERNOP";
1101 auto terminator{sblock->getCFGBlock()->getTerminatorStmt()};
1102 if (llvm::isa<clang::WhileStmt>(terminator)) {
1103 element_str +=
" | WHILE ";
1105 if (llvm::isa<clang::ForStmt>(terminator)) {
1106 element_str +=
" | FOR ";
1108 if (llvm::isa<clang::DoStmt>(terminator)) {
1109 element_str +=
" | DOWHILE ";
1114 auto terminator{sblock->getCFGBlock()->getTerminatorStmt()};
1115 if (llvm::isa<clang::IfStmt>(terminator)) {
1116 element_str +=
" | IF ";
1120 dotos <<
"SB" << sblock->getBlockID() <<
" [ \n label=\"SB"
1121 << sblock->getBlockID() <<
"\n"
1122 << element_str <<
"\"\n]"
1127 for (
auto const& block :
sccfg_) {
1129 for (
auto const& succ : sblock->successors_) {
1130 dotos <<
"SB" << sblock->getBlockID();
1131 dotos <<
" -> SB" << succ->getBlockID() <<
"\n";
1137[[deprecated(
"Use SplitCFG::getAllPathInfo()")]]
const std::unordered_map<
1143const llvm::SmallVector<
1144 std::unordered_map<const SplitCFGBlock*, SplitCFGPathInfo>>&
1149const llvm::SmallVectorImpl<llvm::SmallVector<SplitCFG::SplitCFGPathPair>>&
1155 : context_{context},
1156 next_state_count_{0},
1158 outter_top_(nullptr),
1159 has_ternary_op_{false} {}
1164 const clang::CXXMethodDecl* method)
1165 : context_{context},
1166 next_state_count_{0},
1168 outter_top_(nullptr),
1169 has_ternary_op_{false} {
1180 llvm::dbgs() <<
"########### BFS Identify confluence blocks ############ \n";
1181 std::queue<SplitCFGBlock*> Q{};
1182 std::set<SplitCFGBlock*> discovered{};
1192 discovered.insert(v);
1196 while (!Q.empty()) {
1199 llvm::dbgs() <<
"visited " << v->getBlockID() <<
"\n";
1201 for (
auto succ : v->getCFGBlock()->succs()) {
1202 if (succ && (v->getBlockID() != target->
getBlockID())) {
1203 auto blk{
sccfg_[succ->getBlockID()]};
1204 if (discovered.find(blk) == discovered.end()) {
1205 discovered.insert(blk);
1212 llvm::dbgs() <<
"Discovered\n";
1213 for (
auto disc : discovered ) {
1214 llvm::dbgs() << disc->getBlockID() <<
" ";
1221 llvm::dbgs() <<
"########### Identify confluence blocks ############ \n";
1225 std::vector<SplitCFGBlock*> ternops;
1227 std::vector<SplitCFGBlock*> S{};
1228 std::set<SplitCFGBlock*> discovered{};
1235 while (!S.empty()) {
1238 if (discovered.find(v) == discovered.end()) {
1239 discovered.insert(v);
1240 llvm::dbgs() <<
"visited " << v->
getBlockID() <<
"\n";
1244 if (stmt && clang::dyn_cast<clang::ConditionalOperator>(stmt)) {
1245 llvm::dbgs() <<
"Found a TERNARY OP block\n";
1247 if (!outter) outter = v;
1249 cop_.insert(std::make_pair(v,
nullptr));
1250 ternops.push_back(v);
1252 }
else if (ternops.size() > 0) {
1253 auto top_cop{ternops.back()};
1257 llvm::dbgs() <<
"Found confluence block of " << conf_blk->getBlockID()
1258 <<
" from block " << v->
getBlockID() <<
" of "
1259 << top_cop->getBlockID() <<
"\n";
1260 cop_[top_cop] =
sccfg_[conf_blk->getBlockID()];
1268 if (next_v) S.push_back(
sccfg_[next_v->getBlockID()]);
1273 llvm::dbgs() <<
"Block ids for COP ";
1274 for (
auto& co :
cop_) {
1275 llvm::dbgs() << co.first->getBlockID() <<
" :=> " << co.second->getBlockID()
1278 llvm::dbgs() <<
"\n";
SuccessorIterator::const_iterator const_succ_iterator
SuccessorIterator::const_iterator succ_begin() const
llvm::SmallVector< const SplitCFGBlock * > predecessors_
Predecessors and successors.
void setNextState(unsigned int state)
const clang::CFGBlock * getCFGBlock() const
Returns the pointer to the original CFGBlock from which the SplitCFGBlock was created.
const clang::CFGBlock * block_
A pointer to the original CFGBlock.
bool isLoopWithTwoSuccessors() const
Return whether the SplitCFGBlock is a loop CFGBlock with two succesors.
unsigned int id_
The block id.
bool isConditional() const
Return whether the SplitCFGBlock is an IF CFGBlock.
unsigned int getBlockID() const
Returns the block ID for the SplitCFGBlock.
SuccessorIterator::const_iterator succ_end() const
llvm::SmallVector< const SplitCFGBlock * > successors_
virtual ~SplitCFGPathInfo()
SplitCFGBlockPtrVector true_path_
SplitCFGBlockPtrVector false_path_
SplitCFGPathInfo(const SplitCFGBlock *block)
class SplitCFGPathInfo
const clang::CFGBlock * cfg_block_
void dump() const
Dump the paths.
std::string toStringFalsePath() const
Converts the TRUE path into a string for testing.
SplitCFGPathInfo & operator=(const SplitCFGPathInfo &from)
std::string toStringTruePath() const
Converts the FALSE path into a string for testing.
const SplitCFGBlock * split_block_
unsigned int next_state_count_
SplitCFGPath sub_path_to_special_node_
std::unordered_map< const SplitCFGBlock *, std::pair< const SplitCFGBlock *, unsigned int > > wait_next_state_
Predecessor SplitCFGBlock* => (Wait SplitCFGBlock*)
bool has_ternary_op_
Set to true if the CFG has a ternary operator (ConditionalOperator).
void addSuccessorToVisitOrPop(bool parent_has_wait, const SplitCFGBlock *BB, llvm::SmallVector< std::pair< const SplitCFGBlock *, SplitCFGBlock::const_succ_iterator >, 8 > &to_visit, bool found)
void setTruePathInfo(const SplitCFGBlock *sblock, const SplitCFGPath &newly_visited, int ix=-1)
void splitBlock(clang::CFGBlock *block)
Split a CFGBlock into respective SplitCFGBlock if the CFGBlock has wait statements in it.
bool isConditional(const SplitCFGBlock *block) const
Checks if the block is a conditional. Note that this is different than ternary since the terminator i...
void dumpWaitNextStates() const
void dump() const
Dump member functions.
llvm::SmallVector< const SplitCFGBlock * > VectorSplitCFGBlock
void dumpSmallVector(llvm::SmallVectorImpl< T > &vlist)
bool isElementWait(const clang::CFGElement &element) const
Checks if a CFGBlock has a wait() call in it.
void updateVisitedBlocks(llvm::SmallPtrSetImpl< const SplitCFGBlock * > &to, const llvm::SmallPtrSetImpl< const SplitCFGBlock * > &from)
void dumpPathInfo() const
void generate_paths()
Generates the paths between wait statements.
clang::ASTContext & context_
The context necessary to access translation unit.
void identifyConfluenceBlocks()
Identify confluence blocks in the CFG.
bool getUnvisitedSuccessor(const SplitCFGBlock *curr_block, SplitCFGBlock::const_succ_iterator &I, llvm::SmallPtrSetImpl< const SplitCFGBlock * > &visited, const SplitCFGBlock *&block)
std::set< SplitCFGBlock * > identifySkipBlocks()
bool isTruePath(const SplitCFGBlock *parent_block, const SplitCFGBlock *block) const
void setFalsePathInfo(const SplitCFGBlock *sblock, const SplitCFGPath &newly_visited)
SplitCFG(clang::ASTContext &context)
Constructor.
bool isLoop(const SplitCFGBlock *block) const
Checks if the block is a loop block.
const llvm::SmallVectorImpl< llvm::SmallVector< SplitCFGPathPair > > & getPathsFound()
Returns the paths that were found in the SCCFG.
void dumpCurrPath(SplitCFGPath &curr_path) const
llvm::SmallVector< SplitCFGPathPair > SplitCFGPath
void addSuccessors(SplitCFGBlock *to, const clang::CFGBlock *from)
Add successors to the SplitCFGBlock.
llvm::APInt getWaitArgument(const clang::CFGElement &element) const
Returns the argument to a wait statement. Note that the only one supported are no arguments or intege...
SplitCFGBlock * outter_top_
This is the pointer to the outtermost ternary operator.
llvm::SmallVector< SplitCFGPath > paths_
Paths of BBs generated.
bool isLoopWithTwoSuccessors(const SplitCFGBlock *block) const
void setDifference(const llvm::SmallPtrSetImpl< const SplitCFGBlock * > &larger, const llvm::SmallPtrSetImpl< const SplitCFGBlock * > &smaller, llvm::SmallPtrSetImpl< const SplitCFGBlock * > &to)
Compute the set difference between two SmallPtrSets.
llvm::SmallVector< std::pair< VectorCFGElementPtrImpl, bool > > split_elements
const llvm::SmallVector< std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > > & getAllPathInfo() const
void addPathToSpecialNode(const SplitCFGPath &from)
llvm::SmallVector< std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > > all_path_info_
std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > path_info_
Map a SplitCFGBlock* to its path information. Stores the path information for the blocks that are imp...
std::unordered_map< unsigned int, SplitCFGBlock * > sccfg_
The block id to block for SCCFG.
const std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > & getPathInfo() const
void createWaitSplitCFGBlocks(clang::CFGBlock *block, const llvm::SmallVectorImpl< std::pair< VectorCFGElementPtr, bool > > &split_elements)
Creates the SplitCFGBlocks for CFGBlock with a wait.
bool isTernaryOperator(const SplitCFGBlock *block) const
Checks if the block is contains a terminator that is a ternary operator.
std::map< SplitCFGBlock *, SplitCFGBlock * > getConfluenceBlocks() const
Rework.
llvm::SmallVector< const clang::CFGElement * > VectorCFGElementPtr
void createUnsplitBlocks()
Creates SplitCFGBlocks for all CFGBlocks that do not have a wiat. splitBlock() creates the SplitCFGBl...
std::map< SplitCFGBlock *, SplitCFGBlock * > cop_
virtual ~SplitCFG()
Destructor that erases all SplitCFGBlocks created.
void dumpVisitedBlocks(llvm::SmallPtrSetImpl< const SplitCFGBlock * > &visited)
void addNextStatesToBlocks()
void construct_sccfg(const clang::CXXMethodDecl *method)
Construct the SCCFG.
void dumpSplitElements(const llvm::SmallVector< std::pair< VectorCFGElementPtr, bool > > &split_elements) const
Dump all the CFGElements that were split.
void addPredecessors(SplitCFGBlock *to, const clang::CFGBlock *from)
Add predecessors to the SplitCFGBlock.
void dumpAllPathInfo() const
const SplitCFGPath dfs_visit_wait(const SplitCFGBlock *BB, llvm::SmallPtrSet< const SplitCFGBlock *, 32 > &visited_blocks, llvm::SmallVectorImpl< const SplitCFGBlock * > &waits_to_visit, llvm::SmallPtrSetImpl< const SplitCFGBlock * > &visited_waits, llvm::SmallVector< SplitCFGPathPair > &curr_path)
Modified DFS to create all paths within wait statements and from the root node.
std::unique_ptr< clang::CFG > cfg_
The saved CFG for a given method.
Clang forward declarations.
SupplementaryInfo(const SplitCFGBlock *block)
Construct object using SplitCFGBlock.
int getPathId() const
Returns the path identifier.
int getFalseId() const
Returns the path identifier for the false path.
SupplementaryInfo & operator=(const SupplementaryInfo &from)
virtual ~SupplementaryInfo()
const SplitCFGBlock * getSplitCFGBlock() const
Returns pointer to the SplitCFGBlock.
const SplitCFGBlock * split_block_
Member variables.