Joos1W Compiler Framework
All Classes Functions Typedefs Pages
CGStmt.cc
1 #include "ast/Stmt.h"
2 #include "codegen/CGExpr.h"
3 #include "codegen/CodeGen.h"
4 #include "tir/IRBuilder.h"
5 
6 using namespace tir;
7 using CG = codegen::CodeGenerator;
8 
9 /* ===--------------------------------------------------------------------=== */
10 // Emit specific statements
11 /* ===--------------------------------------------------------------------=== */
12 
13 namespace codegen {
14 
15 void CG::emitForStmt(ast::ForStmt const* stmt) {
16  if(stmt->init()) {
17  emitStmt(stmt->init());
18  }
19  auto cond = builder.createBasicBlock(curFn);
20  auto body = builder.createBasicBlock(curFn);
21  auto afterFor = builder.createBasicBlock(curFn);
22  builder.createBranchInstr(cond);
23  builder.setInsertPoint(cond->begin());
24  if(stmt->condition()) {
25  auto* condVal = emitExpr(stmt->condition());
26  builder.createBranchInstr(condVal, body, afterFor);
27  } else {
28  builder.createBranchInstr(body); // no condition, always branches to body
29  }
30  cond->setName("for.cond");
31  builder.setInsertPoint(body->begin());
32  emitStmt(stmt->body());
33  if(stmt->update()) {
34  emitStmt(stmt->update());
35  }
36  body->setName("for.body");
37  builder.createBranchInstr(cond);
38  builder.setInsertPoint(afterFor->begin());
39 }
40 
41 void CG::emitReturnStmt(ast::ReturnStmt const* stmt) {
42  if(auto expr = stmt->expr()) {
43  auto* val = emitExpr(expr);
44  builder.createReturnInstr(val);
45  } else {
46  builder.createReturnInstr();
47  }
48 }
49 
50 void CG::emitBlockStmt(ast::BlockStatement const* stmt) {
51  for(auto* s : stmt->stmts()) {
52  emitStmt(s);
53  }
54 }
55 
56 void CG::emitDeclStmt(ast::DeclStmt const* stmt) {
57  auto decl = stmt->decl();
58  // Grab the stack slot for the declaration (i.e., alloca inst)
59  assert(valueMap.find(decl) != valueMap.end() &&
60  "Declaration not found in the value map");
61  auto alloca = valueMap[decl];
62  // If there's a declaration, store the value into the stack slot
63  if(auto* init = decl->init()) {
64  auto* val = emitExpr(init);
65  builder.createStoreInstr(val, alloca);
66  }
67 }
68 
69 void CG::emitExprStmt(ast::ExprStmt const* stmt) {
70  CGExprEvaluator eval{*this};
71  eval.EvaluateList(stmt->expr()->list());
72 }
73 
74 void CG::emitIfStmt(ast::IfStmt const* stmt) {
75  auto cond = emitExpr(stmt->condition());
76  auto thenBB = builder.createBasicBlock(curFn);
77  auto elseBB = builder.createBasicBlock(curFn);
78  auto afterIf = builder.createBasicBlock(curFn);
79  builder.createBranchInstr(cond, thenBB, elseBB);
80 
81  // build the then block
82  builder.setInsertPoint(thenBB->begin());
83  emitStmt(stmt->thenStmt());
84  builder.createBranchInstr(afterIf);
85  thenBB->setName("if.then");
86 
87  // build the else block
88  builder.setInsertPoint(elseBB->begin());
89  if(stmt->elseStmt()) {
90  emitStmt(stmt->elseStmt());
91  }
92  builder.createBranchInstr(afterIf);
93  elseBB->setName("if.else");
94 
95  // set the insert point to the afterIf block
96  builder.setInsertPoint(afterIf->begin());
97 }
98 
99 void CG::emitWhileStmt(ast::WhileStmt const* stmt) {
100  auto cond = builder.createBasicBlock(curFn);
101  auto body = builder.createBasicBlock(curFn);
102  auto afterWhile = builder.createBasicBlock(curFn);
103  builder.createBranchInstr(cond);
104 
105  // build the condition block
106  builder.setInsertPoint(cond->begin());
107  auto* condVal = emitExpr(stmt->condition());
108  builder.createBranchInstr(condVal, body, afterWhile);
109  cond->setName("while.cond");
110 
111  // build the body block
112  builder.setInsertPoint(body->begin());
113  emitStmt(stmt->body());
114  builder.createBranchInstr(cond);
115  body->setName("while.body");
116 
117  // set the insert point to the afterWhile block
118  builder.setInsertPoint(afterWhile->begin());
119 }
120 
121 } // namespace codegen
122 
123 /* ===--------------------------------------------------------------------=== */
124 // CodeGenerator emit router
125 /* ===--------------------------------------------------------------------=== */
126 
127 namespace codegen {
128 
129 void CG::emitStmt(ast::Stmt const* stmt) {
130  if(!stmt) return;
131  if(auto* forStmt = dyn_cast<ast::ForStmt>(stmt)) {
132  emitForStmt(forStmt);
133  } else if(auto* retStmt = dyn_cast<ast::ReturnStmt>(stmt)) {
134  emitReturnStmt(retStmt);
135  } else if(auto* blockStmt = dyn_cast<ast::BlockStatement>(stmt)) {
136  emitBlockStmt(blockStmt);
137  } else if(auto* declStmt = dyn_cast<ast::DeclStmt>(stmt)) {
138  emitDeclStmt(declStmt);
139  } else if(auto* exprStmt = dyn_cast<ast::ExprStmt>(stmt)) {
140  emitExprStmt(exprStmt);
141  } else if(auto* ifStmt = dyn_cast<ast::IfStmt>(stmt)) {
142  emitIfStmt(ifStmt);
143  } else if(auto* whileStmt = dyn_cast<ast::WhileStmt>(stmt)) {
144  emitWhileStmt(whileStmt);
145  } else if(auto* nullStmt = dyn_cast<ast::NullStmt>(stmt)) {
146  // Do nothing
147  } else {
148  assert(false && "Unknown statement type");
149  }
150 }
151 
152 } // namespace codegen