3 #include <unordered_map>
7 #include "ast/AstNode.h"
9 #include "ast/DeclContext.h"
11 #include "diagnostics/Location.h"
12 #include "semantic/ConstantTypeResolver.h"
13 #include "semantic/Semantic.h"
14 #include "utils/BumpAllocator.h"
15 #include "utils/DotPrinter.h"
19 using utils::DotPrinter;
25 friend class CFGBuilder;
26 std::pmr::vector<CFGNode*> children;
27 std::pmr::vector<CFGNode*> parents;
28 std::variant<
const ast::Expr*,
const ast::VarDecl*, EmptyExpr> data;
32 mutable bool isVisited;
35 CFGNode(BumpAllocator& alloc,
36 std::variant<
const ast::Expr*,
const ast::VarDecl*, EmptyExpr> data,
37 bool isReturn =
false)
38 : children{alloc}, parents{alloc}, data{data}, isReturn{isReturn} {
44 std::ostream& printDot(std::ostream& os)
const {
45 std::pmr::unordered_map<
const CFGNode*,
int> visited;
48 dp.print(
"compound=true;");
49 printDotNode(dp, visited);
54 utils::Generator<
const CFGNode*> getChildren()
const {
55 for(
auto child : children) {
60 utils::Generator<
const CFGNode*> getParents()
const {
61 for(
auto parent : parents) {
66 std::optional<SourceRange> location()
const {
67 if(std::holds_alternative<
const ast::Expr*>(data)) {
68 return std::get<
const ast::Expr*>(data)->location();
69 }
else if(std::holds_alternative<
const ast::VarDecl*>(data)) {
70 return std::get<
const ast::VarDecl*>(data)->location();
75 std::variant<
const ast::Expr*,
const ast::VarDecl*, EmptyExpr> getData()
const {
78 bool isReturnNode()
const {
return isReturn; }
79 bool isStart()
const {
return start; }
80 bool isInfiniteLoop()
const {
return isInfinite; }
81 bool hasBeenVisited()
const {
return isVisited; }
82 void setVisited(
bool val)
const { isVisited = val; }
85 int printDotNode(utils::DotPrinter& dp,
86 std::pmr::unordered_map<
const CFGNode*,
int>& visited)
const {
87 if(visited.count(
this) > 0) {
93 dp.printTableSingleRow(
"Start", {
"bgcolor",
"lightblue"});
96 dp.printTableSingleRow(
"Return Statement", {
"bgcolor",
"lightblue"});
98 if(std::holds_alternative<
const ast::Expr*>(data)) {
99 std::ostringstream expr;
100 std::get<
const ast::Expr*>(data)->print(expr, -1);
101 dp.printTableSingleRow(
"Expr", {
"bgcolor",
"lightblue"});
102 dp.printTableDoubleRow(
103 "expr", expr.str(), {
"port",
"condition"}, {
"balign",
"left"});
104 }
else if(std::holds_alternative<
const ast::VarDecl*>(data)) {
105 auto name = std::get<
const ast::VarDecl*>(data)->name();
106 dp.printTableSingleRow(
"VarDecl", {
"bgcolor",
"lightblue"});
107 dp.printTableDoubleRow(
108 "expr", name, {
"port",
"condition"}, {
"balign",
"left"});
110 dp.printTableSingleRow(
"Empty Expr", {
"bgcolor",
"lightblue"});
114 for(
auto child : children) {
115 dp.printConnection(id, child->printDotNode(dp, visited));
122 using Heap = std::pmr::memory_resource;
125 std::pmr::vector<CFGNode*> leafs;
127 CFGInfo(BumpAllocator& alloc, CFGNode* head, CFGNode* firstLeaf)
128 : head{head}, leafs{alloc} {
129 leafs.push_back(firstLeaf);
132 CFGInfo(BumpAllocator& alloc, CFGNode* head) : head{head}, leafs{alloc} {}
136 CFGInfo buildIteratively(
const ast::Stmt* stmt, CFGNode* parent =
nullptr);
137 CFGInfo buildForStmt(
const ast::ForStmt* forStmt);
138 CFGInfo buildIfStmt(
const ast::IfStmt* ifStmt);
139 CFGInfo buildDeclStmt(
const ast::DeclStmt* declStmt);
140 CFGInfo buildExprStmt(
const ast::ExprStmt* exprStmt);
141 CFGInfo buildReturnStmt(
const ast::ReturnStmt* returnStmt);
142 CFGInfo buildWhileStmt(
const ast::WhileStmt* whileStmt);
143 CFGInfo buildBlockStmt(
const ast::BlockStatement* blockStmt);
145 void connectCFGNode(CFGNode* parent, CFGNode* child);
146 void connectLeafsToChild(CFGInfo parent, CFGNode* child);
150 ConstantTypeResolver* constTypeResolver, Heap* heap,
156 constTypeResolver{constTypeResolver} {}
157 CFGNode* build(
const ast::Stmt* stmt) {
158 CFGInfo info = buildIteratively(stmt);
159 info.head->start =
true;
166 mutable BumpAllocator alloc;
169 ConstantTypeResolver* constTypeResolver;