systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
SplitCFG.cpp
Go to the documentation of this file.
1// ===-- src/SystemCClang.h - systec-clang class definition -------*- C++
2// -*-===//
3//
4// This file is distributed under the University of Illinois License.
5// See LICENSE.mkd for details.
6//
7// ===----------------------------------------------------------------------===//
8// /
9// / \file
10// / A CFG representation with splitting basic blocks that have wait()
11// statements
12// /
13// ===----------------------------------------------------------------------===//
14
15#include "SplitCFG.h"
16
17#include <regex>
18#include <iostream>
19#include <queue>
20#include <set>
21
22using namespace systemc_clang;
23using namespace clang;
24
29 : split_block_{block}, false_idx_{0}, path_idx_{0} {}
30
32 *this = from;
33}
34
41
43
45
49
51
56 : split_block_{block},
57 cfg_block_{block->getCFGBlock()} {
58 // false_startix = -1;
59 };
60
62 *this = from;
63}
64
68 // false_startix = from.false_startix;
71 path_idx_ = from.path_idx_;
72 return *this;
73}
74
76 std::string str{};
77 for (const auto& block : false_path_) {
78 str += std::to_string(block->getBlockID());
79 str += " ";
80 }
81 if (str.size() > 0) {
82 str.pop_back();
83 }
84
85 return str;
86}
87
89 std::string str{};
90 for (const auto& block : true_path_) {
91 str += std::to_string(block->getBlockID());
92 str += " ";
93 }
94 if (str.size() > 0) {
95 str.pop_back();
96 }
97
98 return str;
99}
100
102 llvm::dbgs() << "* BB# " << split_block_->getBlockID() << ": ";
103 // << " F:" << false_startix << "\n";
104 llvm::dbgs() << "T ";
105 for (const auto block : true_path_) {
106 llvm::dbgs() << block->getBlockID() << " ";
107 }
108 llvm::dbgs() << "; F ";
109 for (const auto block : false_path_) {
110 llvm::dbgs() << block->getBlockID() << " ";
111 }
112 llvm::dbgs() << "*";
113}
114
116
118 for (auto const& path_pair : from) {
119 sub_path_to_special_node_.push_back(path_pair);
120 }
121}
126// const llvm::SmallVector<std::pair<const SplitCFGBlock*, SplitCFGPathInfo>>
128 const SplitCFGBlock* BB,
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};
136
137 SplitCFGPath local_path;
139 if (BB->succ_empty()) {
140 return local_path;
141 }
142
143 popping_ = false;
144 // successors to visit
145 llvm::SmallVector<
146 std::pair<const SplitCFGBlock*, SplitCFGBlock::const_succ_iterator>, 8>
147 to_visit;
148
149 visited_blocks.insert(BB);
150 to_visit.push_back(std::make_pair(BB, BB->succ_begin()));
151
152 // Loop
153 do {
154 std::pair<const SplitCFGBlock*, SplitCFGBlock::const_succ_iterator>& Top =
155 to_visit.back();
156 const SplitCFGBlock* ParentBB{Top.first};
158
160 bool bb_has_wait{(ParentBB->hasWait())};
161 bool cond_block{isConditional(ParentBB)};
162
164 int id{-1};
165 if (!popping_) {
166 llvm::dbgs() << "Visit Parent BB# " << ParentBB->getBlockID() << " ; ";
167 SupplementaryInfo info{ParentBB};
168 info.path_idx_ = curr_path.size();
169 curr_path.push_back(std::make_pair(ParentBB, info));
170 id = curr_path.size() - 1;
171
172 if (!stop_local_path) {
173 local_path.push_back(
174 std::make_pair(ParentBB, SupplementaryInfo{ParentBB}));
175 }
176 } else {
177 // llvm::dbgs() << "POPPING\n";
178 }
181 if (bb_has_wait) {
182 llvm::dbgs() << " has WAIT ";
183 bool found_suc{getUnvisitedSuccessor(ParentBB, I, visited_blocks, BB)};
184 // A wait to be visited is added.
185 if (visited_waits.insert(ParentBB).second) {
186 waits_to_visit.insert(waits_to_visit.begin(), BB);
188 auto wit{wait_next_state_.find(ParentBB)};
189 if (wit == wait_next_state_.end()) {
190 wait_next_state_.insert(
191 std::make_pair(ParentBB, std::make_pair(BB, next_state_count_)));
192 }
193 }
194 }
195
196 // If there is a successor that has not been visited, then remember that
197 // block.
198 llvm::SmallPtrSet<const SplitCFGBlock*, 32> save_visited_blocks{
199 visited_blocks};
200 // dumpVisitedBlocks(visited_blocks);
201
202 bool found_succ{getUnvisitedSuccessor(ParentBB, I, visited_blocks, BB)};
203 if (found_succ) {
204 llvm::dbgs() << "Found successor BB " << BB->getBlockID()
205 << " for parentBB " << ParentBB->getBlockID() << "\n";
206 }
207
208 // Use the recursive call for loops with 2 successors, and IF blocks.
209 // START: LOOP/SPECIAL NODE
210 if ((isLoopWithTwoSuccessors(ParentBB) || isConditional(ParentBB)) &&
211 found_succ) {
212 do {
213 // llvm::dbgs() << "\n==============================================";
214 llvm::dbgs() << "\n#### ParentBB " << ParentBB->getBlockID()
215 << " is a loop with 2 succ or conditional. Succ BB# "
216 << BB->getBlockID() << "\n";
217
221 auto block_path{path_info_.find(ParentBB)};
222 if (block_path != path_info_.end()) {
223 if (const auto true_block_succ = *ParentBB->succ_begin()) {
224 if (true_block_succ == BB) {
225 true_path_ = true;
226 llvm::dbgs() << "Going down the TRUE path for BB"
227 << block_path->first->getBlockID() << " \n";
228
229 } else {
230 false_path_ = true;
231 llvm::dbgs() << "Going down the FALSE path for BB"
232 << block_path->first->getBlockID() << " \n";
233 }
234 }
235 }
236
237 llvm::SmallPtrSet<const SplitCFGBlock*, 32> loop_visited_blocks{
238 save_visited_blocks};
239 // llvm::SmallPtrSet<const SplitCFGBlock*, 32> loop_visited_blocks{};
240
241 // TODO: Do we need this?
242 // visited_blocks.insert(BB);
243
244 // ParentBB has been visited so don't revisit it
245 loop_visited_blocks.insert(ParentBB);
246
247 llvm::dbgs() << "\n==============================================";
248 llvm::dbgs() << "\n[START] Recursive DFS starting at BB "
249 << BB->getBlockID() << " parent BB# "
250 << ParentBB->getBlockID() << " T " << true_path_ << " F "
251 << false_path_ << "\n";
252 llvm::dbgs() << "loop visited ";
253 dumpVisitedBlocks(loop_visited_blocks);
254 llvm::dbgs() << "visited ";
255 dumpVisitedBlocks(visited_blocks);
256 llvm::dbgs() << "local_path : ";
257 dumpSmallVector(local_path);
258 llvm::dbgs() << "\n";
259
260 SplitCFGPath sub_path_to_special_node;
261 // =================== DFS Recurse ====================
262 sub_path_to_special_node = dfs_visit_wait(
263 BB, loop_visited_blocks, waits_to_visit, visited_waits, curr_path);
264 llvm::dbgs() << "\n";
265 // =================== END DFS Recurse ====================
266
267 addPathToSpecialNode(sub_path_to_special_node);
268
271 // updateVisitedBlocks(loop_visited_blocks, loop_visited_blocks);
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 ";
276 dumpVisitedBlocks(loop_visited_blocks);
277 llvm::dbgs() << "visited ";
278 dumpVisitedBlocks(visited_blocks);
279 llvm::dbgs() << "sub_path : ";
280 dumpSmallVector(sub_path_to_special_node);
281
282 llvm::dbgs() << "\n[END] Recurse DFS at BB " << BB->getBlockID()
283 << " parent BB# " << ParentBB->getBlockID() << " T "
284 << true_path_ << " F " << false_path_ << "\n";
285
286 // std::cin.get();
289 // new_visited.insert(BB);
290
291 found_succ = getUnvisitedSuccessor(ParentBB, I, visited_blocks, BB);
292
293 if (true_path_) {
294 llvm::dbgs() << "[TRUE PATH] Set path for BB "
295 << ParentBB->getBlockID() << " to sub_path ";
296 dumpSmallVector(sub_path_to_special_node);
297 llvm::dbgs() << "\n";
298
299 true_path_ = false;
300 auto& info{curr_path[id]};
301 setTruePathInfo(ParentBB, sub_path_to_special_node, curr_path.size());
302 llvm::dbgs() << "curr_path :";
303 dumpSmallVector(curr_path);
304 info.second.false_idx_ = curr_path.size();
305
306 // If there is no successor, then we should find the next block on the
307 // false path and set that to the false_idx_ from curr_path.
308 if (!found_succ) {
309 // There is no successor for ParentBB that is not visited. So, it
310 // must have already been visited, and we must find it in the
311 // curr_path.
312 const clang::CFGBlock* cblock{ParentBB->getCFGBlock()};
313 const clang::CFGBlock* fsucc{*cblock->succ_rbegin()};
314
315 if (fsucc) {
316 fsucc->dump();
317 // Find the index from curr_path, and set it to the false_idx_, if
318 // found.
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_;
322 }
323 }
324 }
325 }
326
327 // llvm::dbgs() << "ID is " << id << " INFO id is "
328 // << info.second.path_idx_ << " SB "
329 // << info.first->getBlockID() << " size of path "
330 // << curr_path.size() << "\n";
331 } else if (false_path_) {
332 // llvm::dbgs() << "FALSE PATH DIFF BB# " << ParentBB->getBlockID();
333 llvm::dbgs() << "[FALSE PATH] Set path for BB "
334 << ParentBB->getBlockID() << " to sub_path ";
335 dumpSmallVector(sub_path_to_special_node);
336 llvm::dbgs() << "\n";
337 false_path_ = false;
338 setFalsePathInfo(ParentBB, sub_path_to_special_node);
339 dumpPathInfo();
341 }
342
343 // dumpVisitedBlocks(new_visited);
344
345 llvm::dbgs() << "\n==============================================";
346
355 //
356
357 if (!found_succ) {
358 llvm::dbgs() << "\nNO SUCCESOR for BB " << ParentBB->getBlockID()
359 << "\n";
360 }
363 if (!found_succ) {
364 updateVisitedBlocks(visited_blocks, loop_visited_blocks);
365 }
366
367 } while (found_succ);
368
369 llvm::dbgs() << "@@@@@@ Exiting loop\n";
371
372 } else {
373 // Recursive call in the if-then will traverse the subgraph.
374 // Only insert successor if recursive call does not visit subgraph.
375 }
376 addSuccessorToVisitOrPop(bb_has_wait, BB, to_visit, found_succ);
377 // std::cin.get();
378 // llvm::dbgs() << "to_visit ";
379 // dumpSmallVector(to_visit);
380 // llvm::dbgs() << " End loop \n";
381 } while (!to_visit.empty());
382 return local_path;
383}
384
386 const SplitCFGPath& newly_visited, int ix) {
387 auto block_path{path_info_.find(sblock)};
388 if (block_path != path_info_.end() && !block_path->second.isTruePathValid()) {
389 // block_path->second.false_startix = ix; // index is start of false path
390 for (const auto block : newly_visited) {
391 block_path->second.true_path_.push_back(block.first);
392 }
393 }
394}
395
397 const SplitCFGPath& newly_visited) {
398 auto block_path{path_info_.find(sblock)};
399 if (block_path != path_info_.end() &&
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() << " ";
404 }
405 }
406}
407
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)) {
414 to.insert(element);
415 }
416 }
417}
418
419bool SplitCFG::isTruePath(const SplitCFGBlock* parent_block,
420 const SplitCFGBlock* block) const {
421 if (!parent_block || !block) {
422 return false;
423 }
424
425 return (*parent_block->succ_begin() == block);
426}
427
429 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& visited) {
430 llvm::dbgs() << " : ";
431 for (const auto sblock : visited) {
432 llvm::dbgs() << sblock->getBlockID() << " ";
433 }
434 llvm::dbgs() << "\n";
435}
436
438 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& to,
439 const llvm::SmallPtrSetImpl<const SplitCFGBlock*>& from) {
440 for (const auto sblock : from) {
441 to.insert(sblock);
442 }
443}
444
446 // The number of successor has to be exactly 2 in order to create a new
447 // visited_blocks.
448 //
449 // Note that CFGBlock often times has a NULL successor. We have to ignore
450 // that.
451 return block->isLoopWithTwoSuccessors();
452}
453
455 bool parent_has_wait, const SplitCFGBlock* BB,
456 llvm::SmallVector<
457 std::pair<const SplitCFGBlock*, SplitCFGBlock::const_succ_iterator>, 8>&
458 to_visit,
459 bool found) {
460 if ((found) && (parent_has_wait == false)) {
461 // Go down one level if there is a unvisited successor.
462 to_visit.push_back(std::make_pair(BB, BB->succ_begin()));
463 popping_ = false;
464 } else {
465 // Go up one level.
466 // llvm::dbgs() << "\npop: " << to_visit.size() << "\n";
467 to_visit.pop_back();
468 popping_ = true;
469 }
470}
471
474 llvm::SmallPtrSetImpl<const SplitCFGBlock*>& visited_blocks,
475 const SplitCFGBlock*& block) {
476 bool found{false};
477 while (I != curr_block->succ_end()) {
478 block = *I++;
479 if ((block != nullptr) && (visited_blocks.insert(block).second)) {
480 found = true;
481 break;
482 }
483 }
484 return found;
485}
486
487bool SplitCFG::isConditional(const SplitCFGBlock* block) const {
490 //
491 if (block == nullptr) {
492 return false;
493 }
494
495 return block->isConditional() && !isTernaryOperator(block);
496}
497
499 if (block == nullptr) {
500 return false;
501 }
502 auto stmt{block->getCFGBlock()->getTerminatorStmt()};
503 return stmt && clang::dyn_cast<clang::ConditionalOperator>(stmt);
504}
505
506bool SplitCFG::isLoop(const SplitCFGBlock* block) const {
509 //
510 if (block == nullptr) {
511 return false;
512 }
513
514 auto stmt{block->getCFGBlock()->getTerminatorStmt()};
515 return stmt &&
516 (llvm::isa<clang::WhileStmt>(stmt) ||
517 llvm::isa<clang::ForStmt>(stmt) || llvm::isa<clang::DoStmt>(stmt));
518}
519
522 VectorSplitCFGBlock waits_to_visit{};
523 llvm::SmallPtrSet<const SplitCFGBlock*, 32> visited_waits;
524
525 const clang::CFGBlock* block{&cfg_->getEntry()};
526 const SplitCFGBlock* entry{sccfg_[block->getBlockID()]};
527 llvm::SmallPtrSet<const SplitCFGBlock*, 32> visited_blocks;
528
530 // llvm::SmallVector<std::pair<const SplitCFGBlock*, SplitCFGPathInfo>>
531 SplitCFGPath curr_path;
532 // Special: Insert root node to start visiting.
533 llvm::dbgs()
534 << "##############################################################\n";
535 llvm::dbgs() << "@@@@@ DFS call for SB " << entry->getBlockID() << "\n";
536 // std::cin.get();
537
538 // Make copy of original paths_info_
539 std::unordered_map<const SplitCFGBlock*, SplitCFGPathInfo>
540 prepared_path_info_{path_info_};
541
542 dfs_visit_wait(entry, visited_blocks, waits_to_visit, visited_waits,
543 curr_path);
544 paths_.push_back(curr_path);
545 llvm::dbgs() << "curr path 1 below\n";
546 dumpCurrPath(curr_path);
547 dumpPaths();
548
549 all_path_info_.push_back(path_info_);
550 path_info_ = prepared_path_info_;
551
552 while (!waits_to_visit.empty()) {
553 curr_path.clear();
554 visited_blocks.clear(); // llvm::SmallPtrSet<const SplitCFGBlock*, 32>
555 // visited_blocks;
556 entry = waits_to_visit.pop_back_val();
557 llvm::dbgs()
558 << "##############################################################\n";
559
560 llvm::dbgs() << "\n@@@@@ DFS call for SB " << entry->getBlockID() << "\n";
561
562 dfs_visit_wait(entry, visited_blocks, waits_to_visit, visited_waits,
563 curr_path);
564 paths_.push_back(curr_path);
565 llvm::dbgs() << "curr path 2 below\n";
566 dumpCurrPath(curr_path);
567 all_path_info_.push_back(path_info_);
568 path_info_ = prepared_path_info_;
569 }
570
573 dumpPaths();
574 dumpPathInfo();
576}
577
579
583llvm::APInt SplitCFG::getWaitArgument(const clang::CFGElement& element) const {
584 if (auto cfg_stmt = element.getAs<clang::CFGStmt>()) {
585 auto stmt{cfg_stmt->getStmt()};
586
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()};
590 if (args == 1) {
591 if (auto first_arg{cxx_me->getArg(0)}) {
592 llvm::dbgs() << "*************** FIRST ARG ****************\n";
593 first_arg->dump();
594
595 // Check if we can evaluate the expression with constant folding
596 // We only accept integer ones. So, for other expressions it might
597 // not work.
598 if (first_arg->isEvaluatable(context_)) {
599 clang::Expr::EvalResult result{};
600 first_arg->EvaluateAsInt(result, context_);
601 llvm::dbgs() << " ARG VAL: ";
602 result.Val.dump();
603 return result.Val.getInt();
604 }
605 }
606 }
607 }
608 }
609 }
610
611 return llvm::APInt{32, 0, false};
612};
613
614bool SplitCFG::isElementWait(const clang::CFGElement& element) const {
615 if (auto cfg_stmt = element.getAs<clang::CFGStmt>()) {
616 auto stmt{cfg_stmt->getStmt()};
617
618 // stmt->dump();
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()};
627 if (args >= 2) {
628 llvm::errs() << "wait() must have either 0 or 1 argument.\n";
629 return false;
630 }
631
632 return true;
633 }
634 }
635 }
636 }
637 }
638
639 return false;
640};
641
642void SplitCFG::splitBlock(clang::CFGBlock* block) {
643 assert(block != nullptr);
644
645 unsigned int num_elements{block->size()};
646
647 llvm::dbgs() << "\n\nChecking if block " << block->getBlockID()
648 << " has a wait()\n";
649 llvm::dbgs() << "Number of elements " << num_elements << "\n";
650 // We are going to have two vectors.
651 // 1. A vector of vector pointers to CFGElements.
652 // 2. A vector of pointers to CFGElements that are waits.
653 //
654
655 VectorCFGElementPtr vec_elements{};
656 llvm::SmallVector<std::pair<VectorCFGElementPtr, bool>> split_elements;
657
659 if (num_elements == 0) {
660 split_elements.push_back(std::make_pair(vec_elements, false));
661 } else {
662 bool has_wait{false};
663 for (auto const& element : block->refs()) {
664 has_wait = false;
665 llvm::dbgs() << "Is this a wait? ";
666 element->dump();
667
671 const clang::CFGElement* element_ptr{element.operator->()};
673 if (isElementWait(*element)) {
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";
678 }
679
680 // Add all elements before the wait into the split elements.
681 if (vec_elements.size() != 0) {
682 split_elements.push_back(std::make_pair(vec_elements, false));
683 vec_elements.clear();
684 }
685
687 vec_elements.push_back(element_ptr);
688 split_elements.push_back(std::make_pair(vec_elements, true));
689 vec_elements.clear();
690
691 has_wait = true;
692 } else {
693 vec_elements.push_back(element_ptr);
694 }
695 }
696
697 if (vec_elements.size() != 0) {
698 split_elements.push_back(std::make_pair(vec_elements, has_wait));
699 }
700 }
701
703}
704
706 clang::CFGBlock* block,
707 const llvm::SmallVectorImpl<std::pair<SplitCFG::VectorCFGElementPtr, bool>>&
708 split_elements) {
709 // dumpSplitElements(split_elements);
711 llvm::dbgs() << "Number of entries in split_elements "
712 << split_elements.size() << "\n";
713 unsigned int id{0};
714 SplitCFGBlock* prev_block{nullptr};
715
716 for (auto const& elements : split_elements) {
717 llvm::dbgs() << "Element number " << id << " ";
719 SplitCFGBlock* new_split{nullptr};
720
721 bool already_exists{false};
722 // id = 0 is when it is the first sequence of elements.
723 if (id == 0) {
724 auto scit{sccfg_.find(block->getBlockID())};
725 // Must be true.
726 // bool already_exists{scit != sccfg_.end()};
727 new_split = scit->second;
728 new_split->id_ = block->getBlockID();
729
730 // Successor: succ block from CFGBlock (overridden)
732 if (split_elements.size() == 1) {
733 addSuccessors(new_split, block);
734 }
735 // Prececessor: prev block from CFGBlock
736 addPredecessors(new_split, block);
737 } else {
738 auto scit{sccfg_.find(block->getBlockID())};
739 new_split = new SplitCFGBlock{}; //*scit->second};
740 new_split->id_ = block->getBlockID() * 10 + id;
741
742 auto is_wait = elements.second;
743 auto stmt{block->getTerminatorStmt()};
744 // A wait block cannot be a conditional.
745 new_split->is_conditional_ =
746 !is_wait && (stmt && (llvm::isa<clang::IfStmt>(stmt) ||
747 llvm::isa<clang::ConditionalOperator>(stmt)));
748
750 //
752 llvm::dbgs() << "SB# " << new_split->id_ << " size "
753 << split_elements.size() << "\n";
754 if (id == split_elements.size() - 1) {
755 llvm::dbgs() << " add successors of BB# " << block->getBlockID()
756 << "\n";
757 addSuccessors(new_split, block);
758 }
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));
763 }
764
765 new_split->block_ = block;
766 new_split->has_wait_ = elements.second;
767 new_split->elements_ = elements.first;
768
769 // If it's a wait() then get the argument.
770 if (new_split->has_wait_) {
772 const clang::CFGElement* wait_el = (*new_split->elements_.begin());
773 new_split->wait_arg_ = getWaitArgument(*wait_el);
774 }
775
778 //
779 if (isLoop(new_split)) {
780 new_split->identifyBreaks(context_);
781 }
782 // Set the successor of new_split.
783 prev_block = new_split;
784 ++id;
785 }
786}
787
788void SplitCFG::addSuccessors(SplitCFGBlock* to, const clang::CFGBlock* from) {
789 for (auto const& succ : from->succs()) {
790 if (succ) {
791 auto fit{sccfg_.find(succ->getBlockID())};
792 SplitCFGBlock* next_succ{fit->second};
793 to->successors_.push_back(next_succ);
794 }
795 }
796}
797
798void SplitCFG::addPredecessors(SplitCFGBlock* to, const clang::CFGBlock* from) {
799 for (auto const& pre : from->preds()) {
800 if (pre) {
801 auto fit{sccfg_.find(pre->getBlockID())};
802 SplitCFGBlock* next_pre{fit->second};
803 to->predecessors_.push_back(next_pre);
804 }
805 }
806}
807
809 llvm::dbgs() << "sccfg( " << sccfg_.size() << ") ids: ";
810 for (auto const& entry : sccfg_) {
811 llvm::dbgs() << entry.first << " ";
812 }
813 llvm::dbgs() << "\n";
814}
815
817 const llvm::SmallVector<std::pair<VectorCFGElementPtr, bool>>&
818 split_elements) const {
819 unsigned int id{0};
820 for (auto const& elements : split_elements) {
821 llvm::dbgs() << "Element number " << id << " has " << elements.first.size()
822 << " items and has ";
823 if (elements.second) {
824 llvm::dbgs() << " a WAIT\n";
825 } else {
826 llvm::dbgs() << " NO WAIT\n";
827 }
828 for (auto const& element : elements.first) {
829 element->dump();
830 }
831
832 ++id;
833 }
834}
835
837
839 for (auto const& wait : wait_next_state_) {
840 SplitCFGBlock* wait_block{const_cast<SplitCFGBlock*>(wait.first)};
841 auto next_block{wait.second.first};
842 auto next_state_id{wait.second.second};
843
844 wait_block->setNextState(next_state_id);
845 }
846}
847
849 llvm::dbgs() << "Dump all wait next states\n";
850 for (auto const& wait : wait_next_state_) {
851 auto wait_block{wait.first};
852 auto next_block{wait.second.first};
853 auto next_state_id{wait.second.second};
854
855 llvm::dbgs() << "SB" << wait_block->getBlockID() << " (SB"
856 << next_block->getBlockID() << ")"
857 << " [S" << next_state_id << "]\n";
858 }
859}
860
862 // llvm::SmallVector<std::pair<const SplitCFGBlock*, SplitCFGPathInfo>>&
863 SplitCFGPath& curr_path) const {
864 llvm::dbgs() << "Dump curr SB path to wait() found in the CFG.\n";
865
866 for (auto const& block : curr_path) {
867 auto sblock{block.first};
868 llvm::dbgs() << sblock->getBlockID() << " ";
869 // Print the wait state
870 auto wit = wait_next_state_.find(sblock);
871 if (wit != wait_next_state_.end()) {
872 auto next_state{wit->second.second};
873 llvm::dbgs() << "[S" << next_state << "] ";
874 }
875 }
876 llvm::dbgs() << "\n";
877}
878
880 llvm::dbgs() << "#### Dump all SB paths to wait() found in the CFG.\n";
881 unsigned int i{0};
882
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_)};
889 // The key thing to remember about the false idx (third element) is that
890 // it is the index created in the path. It points to the index of the
891 // first block that is in the false path.
892 //
893 // (path idx, blockID, false idx).
894
895 llvm::dbgs() << "(" << supp_info.path_idx_ << "," << sblock->getBlockID()
896 << "," << supp_info.false_idx_;
897 if (found_it != path_info_.end()) {
898 llvm::dbgs() << " |" << found_it->second.getFalsePath().size() << "|";
899 if (found_it->second.getFalsePath().size() > 0) {
900 found_it->second.dump();
901 }
902 }
903 llvm::dbgs() << ") ";
904 // Print the wait state
905 auto wit = wait_next_state_.find(sblock);
906 if (wit != wait_next_state_.end()) {
907 auto next_state{wit->second.second};
908 llvm::dbgs() << "[S" << next_state << "] ";
909 }
910 }
911 if (i == 1) {
912 llvm::dbgs() << " (reset path)";
913 }
914
915 llvm::dbgs() << "\n";
916 }
917}
918
920 llvm::dbgs() << "Dump [ALL] path info\n";
921
922 unsigned int i{0};
923 for (const auto& path : all_path_info_) {
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};
928 // llvm::dbgs() << "BB #" << sblock->getBlockID() << "\n";
929 sinfo.dump();
930 llvm::dbgs() << "\n";
931 }
932 ++i;
933 }
934}
935
937 llvm::dbgs() << "Dump all path info\n";
938
939 for (const auto& path_pair : path_info_) {
940 auto sblock{path_pair.first};
941 auto sinfo{path_pair.second};
942 // llvm::dbgs() << "BB #" << sblock->getBlockID() << "\n";
943 sinfo.dump();
944 llvm::dbgs() << "\n";
945 }
946}
947
949 for (auto begin_it = cfg_->nodes_begin(); begin_it != cfg_->nodes_end();
950 ++begin_it) {
951 auto block{*begin_it};
952 SplitCFGBlock* new_block{new SplitCFGBlock{}};
953 new_block->id_ = block->getBlockID();
954
956 auto stmt{block->getTerminatorStmt()};
957 new_block->is_conditional_ =
958 stmt && (llvm::isa<clang::IfStmt>(stmt) ||
959 llvm::isa<clang::ConditionalOperator>(stmt));
960
961 bool last_succ_is_null{false};
962 if (block->succ_size() == 2) {
963 // Check that the last one is not NULL
964 if (*block->succ_rbegin() == nullptr) {
965 last_succ_is_null = true;
966 }
967 }
968
970 bool is_loop{stmt && (llvm::isa<clang::WhileStmt>(stmt) ||
971 llvm::isa<clang::ForStmt>(stmt) ||
972 llvm::isa<clang::DoStmt>(stmt))};
973
974 new_block->is_loop_with_two_succ_ =
975 (stmt && is_loop && (last_succ_is_null == false));
976
977 sccfg_.insert(std::make_pair(new_block->id_, new_block));
978 }
979
980 llvm::dbgs() << "sccfg( " << sccfg_.size() << ") ids: ";
981 for (auto const& entry : sccfg_) {
982 llvm::dbgs() << entry.first << " ";
983 }
984 llvm::dbgs() << "\n";
985}
986
987void SplitCFG::construct_sccfg(const clang::CXXMethodDecl* method) {
988 cfg_ = clang::CFG::buildCFG(method, method->getBody(), &context_,
989 clang::CFG::BuildOptions());
990
991 clang::LangOptions lang_opts;
992 cfg_->dump(lang_opts, true);
993
995
996 for (auto begin_it = cfg_->nodes_begin(); begin_it != cfg_->nodes_end();
997 ++begin_it) {
998 auto block{*begin_it};
999
1000 // Identify whether the CFG block is a ternary operator.
1001 auto stmt{block->getTerminatorStmt()};
1002 if (stmt && clang::dyn_cast<clang::ConditionalOperator>(stmt)) {
1003 has_ternary_op_ = true;
1004 }
1005
1006 splitBlock(block);
1007 }
1009
1010 // Only generate the confluence block map if there is a ternary operator in
1011 // the CFG.
1012 if (has_ternary_op_) {
1014 }
1015
1016 llvm::dbgs() << "\nPrepare to update successors\n";
1017 dumpSCCFG();
1018}
1019
1021 for (auto& block : sccfg_) {
1022 if (isLoopWithTwoSuccessors(block.second) || isConditional(block.second)) {
1023 path_info_.insert(
1024 std::make_pair(block.second, SplitCFGPathInfo(block.second)));
1025 }
1026 }
1027}
1028
1030 for (auto block : sccfg_) {
1031 if (block.second) {
1032 delete block.second;
1033 }
1034 }
1035}
1036
1037void SplitCFG::dump() const {
1038 llvm::dbgs() << "Dump all nodes in SCCFG\n";
1039 for (auto const& block : sccfg_) {
1040 SplitCFGBlock* sblock{block.second};
1041 sblock->dump();
1042 }
1044 dumpPathInfo();
1045 dumpPaths();
1046}
1047
1049 std::error_code OutErrorInfo;
1050 std::error_code ok;
1051 llvm::raw_fd_ostream dotos(llvm::StringRef("sccfg.dot"), OutErrorInfo,
1052 llvm::sys::fs::OF_None);
1053
1054 dotos << "digraph SCCFG {\n";
1055 dotos << " rankdir=TD\n";
1056 dotos << " node [shape=record]\n";
1058 for (auto const& block : sccfg_) {
1059 const SplitCFGBlock* sblock{block.second};
1061
1062 std::string element_str{};
1063 llvm::raw_string_ostream element_os(element_str);
1064 auto num_elements{sblock->getElements().size()};
1065 auto i{0};
1066
1067 element_os << "|{";
1068 for (auto const& element : sblock->getElements()) {
1069 element_os << "| " << i << ":";
1070 element->dumpToStream(element_os);
1071 ++i;
1072 // if (i < num_elements) {
1073 // element_os << "|";
1074 // }
1075 }
1076 element_os << "}";
1077
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, "\\&");
1088
1089 if (sblock->hasWait()) {
1090 dotos << "SB" << sblock->getBlockID() << " [ \n color=red, label=\"SB"
1091 << sblock->getBlockID() << "\n"
1092 << " [" << sblock->getNextState() << "] | WAIT " << element_str
1093 << "\"\n]"
1094 << "\n";
1095 } else {
1096 if (isTernaryOperator(sblock)) {
1097 element_str += " | TERNOP";
1098 }
1099
1100 if (isLoop(sblock)) {
1101 auto terminator{sblock->getCFGBlock()->getTerminatorStmt()};
1102 if (llvm::isa<clang::WhileStmt>(terminator)) {
1103 element_str += " | WHILE ";
1104 }
1105 if (llvm::isa<clang::ForStmt>(terminator)) {
1106 element_str += " | FOR ";
1107 }
1108 if (llvm::isa<clang::DoStmt>(terminator)) {
1109 element_str += " | DOWHILE ";
1110 }
1111 }
1112
1113 if (isConditional(sblock)) {
1114 auto terminator{sblock->getCFGBlock()->getTerminatorStmt()};
1115 if (llvm::isa<clang::IfStmt>(terminator)) {
1116 element_str += " | IF ";
1117 }
1118 }
1119
1120 dotos << "SB" << sblock->getBlockID() << " [ \n label=\"SB"
1121 << sblock->getBlockID() << "\n"
1122 << element_str << "\"\n]"
1123 << "\n";
1124 }
1125 }
1127 for (auto const& block : sccfg_) {
1128 SplitCFGBlock* sblock{block.second};
1129 for (auto const& succ : sblock->successors_) {
1130 dotos << "SB" << sblock->getBlockID();
1131 dotos << " -> SB" << succ->getBlockID() << "\n";
1132 }
1133 }
1134 dotos << "}\n";
1135}
1136
1137[[deprecated("Use SplitCFG::getAllPathInfo()")]] const std::unordered_map<
1140 return path_info_;
1141}
1142
1143const llvm::SmallVector<
1144 std::unordered_map<const SplitCFGBlock*, SplitCFGPathInfo>>&
1146 return all_path_info_;
1147}
1148
1149const llvm::SmallVectorImpl<llvm::SmallVector<SplitCFG::SplitCFGPathPair>>&
1151 return paths_;
1152}
1153
1154SplitCFG::SplitCFG(clang::ASTContext& context)
1155 : context_{context},
1156 next_state_count_{0},
1157 popping_{false},
1158 has_ternary_op_{false} {}
1159// true_path_{false},
1160// false_path_{false} {}
1161
1162SplitCFG::SplitCFG(clang::ASTContext& context,
1163 const clang::CXXMethodDecl* method)
1164 : context_{context},
1165 next_state_count_{0},
1166 popping_{false},
1167 has_ternary_op_{false} {
1168 // true_path_{false},
1169 // false_path_{false} {
1170 construct_sccfg(method);
1171}
1172
1173std::map<SplitCFGBlock*, SplitCFGBlock*> SplitCFG::getConfluenceBlocks() const {
1174 return cop_;
1175}
1176
1177std::set<SplitCFGBlock*> SplitCFG::identifySkipBlocks() {
1178 llvm::dbgs() << "########### BFS Identify confluence blocks ############ \n";
1179 std::queue<SplitCFGBlock*> Q{};
1180 std::set<SplitCFGBlock*> discovered{};
1181
1183 SplitCFGBlock* target = cop_[outter_top];
1184 llvm::dbgs() << "Outter ternop is BB" << outter_top->getBlockID() << " and confluence block is BB" << target->getBlockID() << "\n";
1185 // if (!source) v = sccfg_[cfg_->getEntry().getBlockID()];
1186 // else v = source;
1187
1188 discovered.insert(v);
1189
1190 Q.push(v);
1191
1192 while (!Q.empty()) {
1193 v = Q.front();
1194 Q.pop();
1195 llvm::dbgs() << "visited " << v->getBlockID() << "\n";
1196
1197 for (auto succ : v->getCFGBlock()->succs()) {
1198 if (succ && (v->getBlockID() != target->getBlockID())) {
1199 auto blk{sccfg_[succ->getBlockID()]};
1200 if (discovered.find(blk) == discovered.end()) {
1201 discovered.insert(blk);
1202 Q.push(blk);
1203 }
1204 }
1205 }
1206 }
1207
1208 llvm::dbgs() << "Discovered\n";
1209 for (auto disc : discovered ) {
1210 llvm::dbgs() << disc->getBlockID() <<" ";
1211
1212 }
1213 return discovered;
1214}
1215
1217 llvm::dbgs() << "########### Identify confluence blocks ############ \n";
1218
1219 // ConditionalOperator block => Confluence Block
1220 // std::map<SplitFGBlock*, SplitCFGBlock*> cop_;
1221 std::vector<SplitCFGBlock*> ternops;
1222
1223 std::vector<SplitCFGBlock*> S{};
1224 std::set<SplitCFGBlock*> discovered{};
1225 // Do DFS whenever you reach a conditional operator block.
1226 SplitCFGBlock* v = sccfg_[cfg_->getEntry().getBlockID()];
1227
1228 SplitCFGBlock* outter{nullptr};
1229
1230 S.push_back(v);
1231 while (!S.empty()) {
1232 v = S.back();
1233 S.pop_back();
1234 if (discovered.find(v) == discovered.end()) {
1235 discovered.insert(v);
1236 llvm::dbgs() << "visited " << v->getBlockID() << "\n";
1237
1238 // Found ConditionalOperator
1239 auto stmt{v->getCFGBlock()->getTerminatorStmt()};
1240 if (stmt && clang::dyn_cast<clang::ConditionalOperator>(stmt)) {
1241 llvm::dbgs() << "Found a TERNARY OP block\n";
1242
1243 if (!outter) outter = v;
1244
1245 cop_.insert(std::make_pair(v, nullptr));
1246 ternops.push_back(v);
1247
1248 } else if (ternops.size() > 0) {
1249 auto top_cop{ternops.back()};
1250 // Successor is the confluence
1251 if (v->getCFGBlock()->succ_size() == 1) {
1252 auto conf_blk{*v->getCFGBlock()->succ_begin()};
1253 llvm::dbgs() << "Found confluence block of " << conf_blk->getBlockID()
1254 << " from block " << v->getBlockID() << " of "
1255 << top_cop->getBlockID() << "\n";
1256 cop_[top_cop] = sccfg_[conf_blk->getBlockID()];
1257
1258 conf_blk->dump();
1259 ternops.pop_back();
1260 }
1261 }
1262
1263 for (auto next_v : v->getCFGBlock()->succs()) {
1264 if (next_v) S.push_back(sccfg_[next_v->getBlockID()]);
1265 }
1266 }
1267 }
1268 // Print the cop map.
1269 llvm::dbgs() << "Block ids for COP ";
1270 for (auto& co : cop_) {
1271 llvm::dbgs() << co.first->getBlockID() << " :=> " << co.second->getBlockID()
1272 << " ; ";
1273 }
1274 llvm::dbgs() << "\n";
1275
1276 outter_top = outter;
1277}
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.
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_
SplitCFGBlockPtrVector true_path_
Definition SplitCFG.h:86
SplitCFGBlockPtrVector false_path_
Definition SplitCFG.h:85
SplitCFGPathInfo(const SplitCFGBlock *block)
class SplitCFGPathInfo
Definition SplitCFG.cpp:55
const clang::CFGBlock * cfg_block_
Definition SplitCFG.h:83
void dump() const
Dump the paths.
Definition SplitCFG.cpp:101
std::string toStringFalsePath() const
Converts the TRUE path into a string for testing.
Definition SplitCFG.cpp:75
SplitCFGPathInfo & operator=(const SplitCFGPathInfo &from)
Definition SplitCFG.cpp:65
std::string toStringTruePath() const
Converts the FALSE path into a string for testing.
Definition SplitCFG.cpp:88
const SplitCFGBlock * split_block_
Definition SplitCFG.h:82
unsigned int next_state_count_
Definition SplitCFG.h:137
SplitCFGPath sub_path_to_special_node_
Definition SplitCFG.h:135
std::unordered_map< const SplitCFGBlock *, std::pair< const SplitCFGBlock *, unsigned int > > wait_next_state_
Predecessor SplitCFGBlock* => (Wait SplitCFGBlock*)
Definition SplitCFG.h:125
bool has_ternary_op_
Set to true if the CFG has a ternary operator (ConditionalOperator).
Definition SplitCFG.h:140
void addSuccessorToVisitOrPop(bool parent_has_wait, const SplitCFGBlock *BB, llvm::SmallVector< std::pair< const SplitCFGBlock *, SplitCFGBlock::const_succ_iterator >, 8 > &to_visit, bool found)
Definition SplitCFG.cpp:454
void setTruePathInfo(const SplitCFGBlock *sblock, const SplitCFGPath &newly_visited, int ix=-1)
Definition SplitCFG.cpp:385
void splitBlock(clang::CFGBlock *block)
Split a CFGBlock into respective SplitCFGBlock if the CFGBlock has wait statements in it.
Definition SplitCFG.cpp:642
bool isConditional(const SplitCFGBlock *block) const
Checks if the block is a conditional. Note that this is different than ternary since the terminator i...
Definition SplitCFG.cpp:487
void dumpWaitNextStates() const
Definition SplitCFG.cpp:848
void dump() const
Dump member functions.
llvm::SmallVector< const SplitCFGBlock * > VectorSplitCFGBlock
Definition SplitCFG.h:98
void dumpSmallVector(llvm::SmallVectorImpl< T > &vlist)
Definition SplitCFG.h:247
bool isElementWait(const clang::CFGElement &element) const
Checks if a CFGBlock has a wait() call in it.
Definition SplitCFG.cpp:614
void updateVisitedBlocks(llvm::SmallPtrSetImpl< const SplitCFGBlock * > &to, const llvm::SmallPtrSetImpl< const SplitCFGBlock * > &from)
Definition SplitCFG.cpp:437
void dumpPathInfo() const
Definition SplitCFG.cpp:936
void generate_paths()
Generates the paths between wait statements.
Definition SplitCFG.cpp:836
clang::ASTContext & context_
The context necessary to access translation unit.
Definition SplitCFG.h:106
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)
Definition SplitCFG.cpp:472
std::set< SplitCFGBlock * > identifySkipBlocks()
bool isTruePath(const SplitCFGBlock *parent_block, const SplitCFGBlock *block) const
Definition SplitCFG.cpp:419
void setFalsePathInfo(const SplitCFGBlock *sblock, const SplitCFGPath &newly_visited)
Definition SplitCFG.cpp:396
SplitCFG(clang::ASTContext &context)
Constructor.
bool isLoop(const SplitCFGBlock *block) const
Checks if the block is a loop block.
Definition SplitCFG.cpp:506
const llvm::SmallVectorImpl< llvm::SmallVector< SplitCFGPathPair > > & getPathsFound()
Returns the paths that were found in the SCCFG.
void dumpCurrPath(SplitCFGPath &curr_path) const
Definition SplitCFG.cpp:861
llvm::SmallVector< SplitCFGPathPair > SplitCFGPath
Definition SplitCFG.h:95
void addSuccessors(SplitCFGBlock *to, const clang::CFGBlock *from)
Add successors to the SplitCFGBlock.
Definition SplitCFG.cpp:788
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...
Definition SplitCFG.cpp:583
llvm::SmallVector< SplitCFGPath > paths_
Paths of BBs generated.
Definition SplitCFG.h:115
bool isLoopWithTwoSuccessors(const SplitCFGBlock *block) const
Definition SplitCFG.cpp:445
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.
Definition SplitCFG.cpp:408
llvm::SmallVector< std::pair< VectorCFGElementPtrImpl, bool > > split_elements
Definition SplitCFG.h:120
const llvm::SmallVector< std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > > & getAllPathInfo() const
void addPathToSpecialNode(const SplitCFGPath &from)
Definition SplitCFG.cpp:117
llvm::SmallVector< std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > > all_path_info_
Definition SplitCFG.h:133
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...
Definition SplitCFG.h:130
std::unordered_map< unsigned int, SplitCFGBlock * > sccfg_
The block id to block for SCCFG.
Definition SplitCFG.h:118
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.
Definition SplitCFG.cpp:705
bool isTernaryOperator(const SplitCFGBlock *block) const
Checks if the block is contains a terminator that is a ternary operator.
Definition SplitCFG.cpp:498
SplitCFGBlock * outter_top
Definition SplitCFG.h:244
std::map< SplitCFGBlock *, SplitCFGBlock * > getConfluenceBlocks() const
Rework.
llvm::SmallVector< const clang::CFGElement * > VectorCFGElementPtr
Definition SplitCFG.h:102
void createUnsplitBlocks()
Creates SplitCFGBlocks for all CFGBlocks that do not have a wiat. splitBlock() creates the SplitCFGBl...
Definition SplitCFG.cpp:948
std::map< SplitCFGBlock *, SplitCFGBlock * > cop_
Definition SplitCFG.h:144
virtual ~SplitCFG()
Destructor that erases all SplitCFGBlocks created.
void dumpVisitedBlocks(llvm::SmallPtrSetImpl< const SplitCFGBlock * > &visited)
Definition SplitCFG.cpp:428
void construct_sccfg(const clang::CXXMethodDecl *method)
Construct the SCCFG.
Definition SplitCFG.cpp:987
void dumpSplitElements(const llvm::SmallVector< std::pair< VectorCFGElementPtr, bool > > &split_elements) const
Dump all the CFGElements that were split.
Definition SplitCFG.cpp:816
void addPredecessors(SplitCFGBlock *to, const clang::CFGBlock *from)
Add predecessors to the SplitCFGBlock.
Definition SplitCFG.cpp:798
void dumpAllPathInfo() const
Definition SplitCFG.cpp:919
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.
Definition SplitCFG.cpp:127
std::unique_ptr< clang::CFG > cfg_
The saved CFG for a given method.
Definition SplitCFG.h:109
Clang forward declarations.
Definition FindArgument.h:6
SupplementaryInfo(const SplitCFGBlock *block)
Construct object using SplitCFGBlock.
Definition SplitCFG.cpp:28
int getPathId() const
Returns the path identifier.
Definition SplitCFG.cpp:42
int getFalseId() const
Returns the path identifier for the false path.
Definition SplitCFG.cpp:44
SupplementaryInfo & operator=(const SupplementaryInfo &from)
Definition SplitCFG.cpp:35
const SplitCFGBlock * getSplitCFGBlock() const
Returns pointer to the SplitCFGBlock.
Definition SplitCFG.cpp:46
const SplitCFGBlock * split_block_
Member variables.
Definition SplitCFG.h:35