1 #include "semantic/CFGBuilder.h"
5 #include "ast/AstNode.h"
7 #include "utils/Utils.h"
14 assert(stmt &&
"stmt is nullptr");
15 CFGInfo node = {alloc,
nullptr};
16 if(
auto forStmt = dyn_cast<ast::ForStmt>(stmt)) {
17 node = buildForStmt(forStmt);
18 }
else if(
auto ifStmt = dyn_cast<ast::IfStmt>(stmt)) {
19 node = buildIfStmt(ifStmt);
20 }
else if(
auto declStmt = dyn_cast<ast::DeclStmt>(stmt)) {
21 node = buildDeclStmt(declStmt);
22 }
else if(
auto exprStmt = dyn_cast<ast::ExprStmt>(stmt)) {
23 node = buildExprStmt(exprStmt);
24 }
else if(
auto returnStmt = dyn_cast<ast::ReturnStmt>(stmt)) {
25 node = buildReturnStmt(returnStmt);
26 }
else if(
auto whileStmt = dyn_cast<ast::WhileStmt>(stmt)) {
27 node = buildWhileStmt(whileStmt);
28 }
else if(
auto blockStmt = dyn_cast<ast::BlockStatement>(stmt)) {
29 node = buildBlockStmt(blockStmt);
32 return CFGInfo{alloc, empty, empty};
36 return CFGInfo{alloc, empty, empty};
39 assert(node.head &&
"node is nullptr");
42 connectCFGNode(parent, node.head);
48 const ast::BlockStatement* blockStmt) {
49 CFGInfo node = {alloc,
nullptr}, parent = {alloc,
nullptr},
50 head = {alloc,
nullptr};
51 for(
auto stmt : blockStmt->stmts()) {
52 if(parent.head ==
nullptr) {
53 parent = buildIteratively(stmt);
56 node = buildIteratively(stmt);
57 connectLeafsToChild(parent, node.head);
61 CFGInfo info = CFGInfo{alloc, head.head};
62 for(
auto leaf : parent.leafs) {
63 info.leafs.push_back(leaf);
69 CFGNode* node = alloc.new_object<
CFGNode>(alloc, declStmt->decl());
70 return CFGInfo{alloc, node, node};
74 CFGNode* node = alloc.new_object<
CFGNode>(alloc, exprStmt->expr());
75 return CFGInfo{alloc, node, node};
80 CFGInfo init = {alloc,
nullptr};
82 init = buildIteratively(forStmt->init());
85 if(forStmt->condition()) {
86 condition = alloc.new_object<
CFGNode>(alloc, forStmt->condition());
87 ConstantReturnType
const* ret =
88 constTypeResolver->Evaluate(forStmt->condition());
90 if(ret->constantType == ConstantReturnType::type::BOOL) {
92 diag.ReportError(forStmt->condition()->location())
93 <<
"Unreachable statement in for loop body";
95 assert(ret->value == 1 &&
"invalid boolean value");
102 if(init.head) connectCFGNode(init.head, condition);
103 CFGInfo body = buildIteratively(forStmt->body(), condition);
104 if(forStmt->update()) {
105 CFGInfo update = buildIteratively(forStmt->update());
106 connectLeafsToChild(body, update.head);
107 connectLeafsToChild(update, condition);
109 connectLeafsToChild(body, condition);
111 if(init.head)
return CFGInfo{alloc, init.head, condition};
112 return CFGInfo{alloc, condition, condition};
116 CFGNode* condition = alloc.new_object<
CFGNode>(alloc, ifStmt->condition());
118 CFGInfo info = {alloc, condition};
120 CFGInfo ifNode = buildIteratively(ifStmt->thenStmt(), condition);
121 info.leafs.insert(info.leafs.end(), ifNode.leafs.begin(), ifNode.leafs.end());
122 if(ifStmt->elseStmt()) {
123 CFGInfo elseNode = buildIteratively(ifStmt->elseStmt(), condition);
125 info.leafs.end(), elseNode.leafs.begin(), elseNode.leafs.end());
128 info.leafs.push_back(empty);
129 connectCFGNode(condition, empty);
135 const ast::ReturnStmt* returnStmt) {
137 if(returnStmt->expr() ==
nullptr) {
140 node = alloc.new_object<
CFGNode>(alloc, returnStmt->expr(),
true);
142 return CFGInfo{alloc, node, node};
146 CFGNode* condition = alloc.new_object<
CFGNode>(alloc, whileStmt->condition());
147 ConstantReturnType
const* ret =
148 constTypeResolver->Evaluate(whileStmt->condition());
150 if(ret->constantType == ConstantReturnType::type::BOOL) {
151 if(ret->value == 0) {
152 diag.ReportError(whileStmt->condition()->location())
153 <<
"Unreachable statement in while loop body";
154 }
else if(ret->value == 1) {
155 condition->setVisited(
true);
158 assert(
false &&
"invalid boolean value");
162 if(whileStmt->body()) {
163 CFGInfo body = buildIteratively(whileStmt->body(), condition);
164 connectLeafsToChild(body, condition);
167 return CFGInfo{alloc, condition, leafNode};
169 return CFGInfo{alloc, condition};
173 parent->children.push_back(child);
174 child->parents.push_back(parent);
178 for(
auto leaf : parent.leafs) {
179 connectCFGNode(leaf, child);
181 if(child->parents.empty()) {
182 if(child->location()) {
183 diag.ReportError(child->location().value()) <<
"Unreachable statement";
185 diag.ReportError(parent.head->location().value()) <<
"Unreachable statement";