Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//===--- GenFunc.cpp ------------------------------------------------------===//
//
// dusk-lang
// This source file is part of a dusk-lang project, which is a semestral
// assignement for BI-PJP course at Czech Technical University in Prague.
// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
//
//===----------------------------------------------------------------------===//
#include "GenFunc.h"
#include "dusk/AST/Decl.h"
#include "dusk/AST/Expr.h"
#include "dusk/AST/Stmt.h"
#include "dusk/AST/Pattern.h"
#include "dusk/AST/Type.h"
#include "dusk/AST/Decl.h"
#include "dusk/AST/ASTVisitor.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Type.h"
#include "GenExpr.h"
#include "IRGenFunc.h"
using namespace dusk;
using namespace irgen;
static llvm::Value *emitCond(IRGenFunc &IRGF, Expr *E) {
auto Cond = codegenExpr(IRGF.IRGM, E);
auto Ty = llvm::Type::getInt64Ty(IRGF.IRGM.LLVMContext);
auto Zero = llvm::ConstantInt::get(Ty, 0);
return IRGF.Builder.CreateICmpNE(Cond, Zero, "ifcond");
}
namespace {
class GenFunc: public ASTVisitor<GenFunc,
/* Decl */ bool,
/* Expr */ bool,
/* Stmt */ bool,
/* Pattern */ bool,
/* TypeRepr */ bool> {
typedef ASTVisitor super;
IRGenFunc &IRGF;
public:
GenFunc(IRGenFunc &IRGF) : IRGF(IRGF) {}
bool visitLetDecl(ValDecl *D) {
return IRGF.declare(D).isValid();
}
bool visitVarDecl(ValDecl *D) {
if (auto D = dynamic_cast<Decl *>(N)) {
if (!super::visit(D))
return false;
} else if (auto E = dynamic_cast<Expr *>(N)) {
if (!super::visit(E))
return false;
} else if (auto S = dynamic_cast<Stmt *>(N)) {
if (!super::visit(S))
return false;
} else {
llvm_unreachable("Unexpected node.");
}
// Get end block of top level loop
auto EndBB = IRGF.LoopStack.getInfo().getEndBlock();
return IRGF.Builder.CreateBr(EndBB) != nullptr;
}
if (!IRGF.Fn->getReturnType()->isVoidTy()) {
auto RetVal = codegenExpr(IRGF.IRGM, S->getValue());
IRGF.setRetVal(RetVal);
}
IRGF.Builder.CreateBr(IRGF.getRetBlock());
return true;
}
// Create basic blocks
auto ThenBB =
llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "if.then", IRGF.Fn);
auto ElseBB = llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "if.else");
auto ContBB = llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "if.cont");
// Add basic blocks to function
IRGF.Fn->getBasicBlockList().push_back(ElseBB);
IRGF.Fn->getBasicBlockList().push_back(ContBB);
// Emit conditional jump
auto Cond = emitCond(IRGF, S->getCond());
if (S->hasElseBlock())
IRGF.Builder.CreateCondBr(Cond, ThenBB, ElseBB);
else
IRGF.Builder.CreateCondBr(Cond, ThenBB, ContBB);
// Emit Then branch
IRGF.Builder.SetInsertPoint(ThenBB);
IRGF.IRGM.Lookup.push();
return false;
IRGF.IRGM.Lookup.pop();
if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr)
IRGF.Builder.CreateBr(ContBB);
// Emit else branch
if (S->hasElseBlock()) {
IRGF.Builder.SetInsertPoint(ElseBB);
IRGF.IRGM.Lookup.push();
return false;
IRGF.IRGM.Lookup.pop();
if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr)
IRGF.Builder.CreateBr(ContBB);
} else {
ElseBB->removeFromParent();
}
// Set pointer to the cont block.
IRGF.Builder.SetInsertPoint(ContBB);
return true;
}
// Create loop blocks
auto HeaderBlock =
llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "loop.header", IRGF.Fn);
auto BodyBlock =
llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "loop.body");
auto EndBlock = llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "loop.end");
IRGF.IRGM.Lookup.push();
IRGF.LoopStack.push(HeaderBlock, EndBlock);
// Add block to function.
IRGF.Fn->getBasicBlockList().push_back(BodyBlock);
IRGF.Fn->getBasicBlockList().push_back(EndBlock);
IRGF.Builder.CreateBr(HeaderBlock);
// Emit condition
IRGF.Builder.SetInsertPoint(HeaderBlock);
auto Cond = emitCond(IRGF, S->getCond());
IRGF.Builder.CreateCondBr(Cond, BodyBlock, EndBlock);
// Emit loop body
IRGF.Builder.SetInsertPoint(BodyBlock);
return false;
// Jump back to the condition
if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr)
IRGF.Builder.CreateBr(HeaderBlock);
IRGF.Builder.SetInsertPoint(EndBlock);
IRGF.LoopStack.pop();
IRGF.IRGM.Lookup.pop();
return true;
}
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Create loop blocks
auto HeaderBlock =
llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "loop.header", IRGF.Fn);
auto BodyBlock =
llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "loop.body");
auto EndBlock = llvm::BasicBlock::Create(IRGF.IRGM.LLVMContext, "loop.end");
IRGF.IRGM.Lookup.push();
IRGF.LoopStack.push(HeaderBlock, EndBlock);
// Add block to function.
IRGF.Fn->getBasicBlockList().push_back(BodyBlock);
IRGF.Fn->getBasicBlockList().push_back(EndBlock);
// Emit initialization
auto Iter = IRGF.declare(S->getIter());
auto Rng = static_cast<RangeStmt *>(S->getRange());
auto Val = codegenExpr(IRGF.IRGM, Rng->getStart());
IRGF.Builder.CreateStore(Val, Iter);
IRGF.Builder.CreateBr(HeaderBlock);
// Emit condition
IRGF.Builder.SetInsertPoint(HeaderBlock);
auto LHS = IRGF.Builder.CreateLoad(Iter);
auto RHS = codegenExpr(IRGF.IRGM, Rng->getEnd());
auto Cond = IRGF.Builder.CreateICmpNE(LHS, RHS);
IRGF.Builder.CreateCondBr(Cond, BodyBlock, EndBlock);
// Emit loop body
IRGF.Builder.SetInsertPoint(BodyBlock);
return false;
// Jump back to the condition
auto Ty = llvm::Type::getInt64Ty(IRGF.IRGM.LLVMContext);
auto IV = llvm::ConstantInt::get(Ty, 1);
auto Incr = IRGF.Builder.CreateAdd(IRGF.Builder.CreateLoad(Iter), IV);
IRGF.Builder.CreateStore(Incr, Iter);
if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr)
IRGF.Builder.CreateBr(HeaderBlock);
IRGF.Builder.SetInsertPoint(EndBlock);
IRGF.LoopStack.pop();
IRGF.IRGM.Lookup.pop();
return true;
}
bool visitFuncStmt(FuncStmt *S) { return true; }
bool visitRangeStmt(RangeStmt *S) { return true; }
bool visitSubscriptStmt(SubscriptStmt *S) { return true; }
bool visitExternStmt(ExternStmt *S) { return true; }
bool visitFuncDecl(FuncDecl *S) { return true; }
bool visitModuleDecl(ModuleDecl *D) { return true; }
bool visitParamDecl(ParamDecl *D) { return true; }
bool visitNumberLiteralExpr(NumberLiteralExpr *E) {
bool visitArrayLiteralExpr(ArrayLiteralExpr *E) {
bool visitIdentifierExpr(IdentifierExpr *E) {
bool visitSubscriptExpr(SubscriptExpr *E) {
return codegenExpr(IRGF.IRGM, E) != nullptr;
}
};
} // anonymous namespace
bool irgen::genFunc(IRGenFunc &IRGF, FuncStmt *F) {
GenFunc GF(IRGF);
return GF.ASTVisitor::visit(F->getBody());