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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include "cps/CodeGen.h"
#include "llvm/IR/Verifier.h"
using namespace llvm;
using namespace cps;
CodeGen::CodeGen() {
TheContext = std::make_unique<LLVMContext>();
TheModule = std::make_unique<Module>("cps_module", *TheContext);
Builder = std::make_unique<IRBuilder<>>(*TheContext);
SetupExternalFunctions();
}
void CodeGen::SetupExternalFunctions() {
// printf(i8*, ...)
std::vector<Type*> PrintfArgs;
PrintfArgs.push_back(PointerType::getUnqual(*TheContext));
FunctionType *PrintfType = FunctionType::get(Type::getInt32Ty(*TheContext), PrintfArgs, true);
PrintfFunc = TheModule->getOrInsertFunction("printf", PrintfType);
// scanf(i8*, ...)
FunctionType *ScanfType = FunctionType::get(Type::getInt32Ty(*TheContext), PrintfArgs, true);
ScanfFunc = TheModule->getOrInsertFunction("scanf", ScanfType);
// format %d\n and %d
PrintfFormatStr = Builder->CreateGlobalStringPtr("%d\n", "fmt_nl", 0, TheModule.get());
ScanfFormatStr = Builder->CreateGlobalStringPtr("%d", "fmt_in", 0, TheModule.get());
}
AllocaInst *CodeGen::CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) {
IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
return TmpB.CreateAlloca(Type::getInt32Ty(*TheContext), nullptr, VarName);
}
void CodeGen::compile(const std::vector<std::unique_ptr<StmtAST>> &Statements) {
FunctionType *FT = FunctionType::get(Type::getInt32Ty(*TheContext), false);
Function *F = Function::Create(FT, Function::ExternalLinkage, "main", TheModule.get());
BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(BB);
for (const auto &Stmt : Statements) {
// DECLARE
if (auto *Decl = dynamic_cast<DeclareStmtAST*>(Stmt.get())) {
AllocaInst *Alloca = CreateEntryBlockAlloca(F, Decl->getName());
NamedValues[Decl->getName()] = Alloca;
// 0
Builder->CreateStore(ConstantInt::get(*TheContext, APInt(32, 0)), Alloca);
}
// ASSIGNMENT (x <- expr)
else if (auto *Assign = dynamic_cast<AssignStmtAST*>(Stmt.get())) {
Value *Val = nullptr;
if (auto *Num = dynamic_cast<NumberExprAST*>(Assign->getExpr())) {
Val = ConstantInt::get(*TheContext, APInt(32, Num->getVal()));
} else if (auto *Var = dynamic_cast<VariableExprAST*>(Assign->getExpr())) {
AllocaInst *A = NamedValues[Var->getName()];
Val = Builder->CreateLoad(Type::getInt32Ty(*TheContext), A, Var->getName());
}
AllocaInst *Alloca = NamedValues[Assign->getName()];
if (Alloca && Val) {
Builder->CreateStore(Val, Alloca);
}
}
// INPUT
else if (auto *In = dynamic_cast<InputStmtAST*>(Stmt.get())) {
AllocaInst *Alloca = NamedValues[In->getName()];
if (Alloca) {
std::vector<Value*> Args;
Args.push_back(ScanfFormatStr);
Args.push_back(Alloca);
Builder->CreateCall(ScanfFunc, Args);
}
}
// OUTPUT
else if (auto *Out = dynamic_cast<OutputStmtAST*>(Stmt.get())) {
Value *Val = nullptr;
if (auto *Num = dynamic_cast<NumberExprAST*>(Out->getExpr())) {
Val = ConstantInt::get(*TheContext, APInt(32, Num->getVal()));
} else if (auto *Var = dynamic_cast<VariableExprAST*>(Out->getExpr())) {
AllocaInst *A = NamedValues[Var->getName()];
Val = Builder->CreateLoad(Type::getInt32Ty(*TheContext), A, Var->getName());
}
if (Val) {
// printf("%d\n", val)
std::vector<Value*> Args;
Args.push_back(PrintfFormatStr);
Args.push_back(Val);
Builder->CreateCall(PrintfFunc, Args);
}
}
}
// main return 0
Builder->CreateRet(ConstantInt::get(*TheContext, APInt(32, 0)));
verifyFunction(*F);
}
void CodeGen::print() {
TheModule->print(errs(), nullptr);
}
|