-
Notifications
You must be signed in to change notification settings - Fork 0
/
Expr.cpp
162 lines (147 loc) · 4.54 KB
/
Expr.cpp
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "Expr.hpp"
#include "Compiler.hpp"
using namespace llvm;
Value *intExpr::codegen() {
return Compiler::getInstance().emitInt(this->mVal);
}
Value *doubleExpr::codegen() {
return Compiler::getInstance().emitDouble(this->mVal);
}
llvm::Value *boolExpr::codegen() {
return Compiler::getInstance().emitBoolean(this->mVal);
}
Value *VariableExpr::codegen() {
// Look this variable up in the function.
AllocaInst *V = Compiler::getInstance().getNamedValue(Name);
if (!V) {
std::cout << "Unknown variable name";
return nullptr;
}
return Compiler::getInstance().emitLoad(V, Name);
}
llvm::Value *VarExprAST::codegen() {
return Compiler::getInstance().emitVar(std::move(VarNames));
}
Value *BinaryExpr::codegen() {
// Special case '=' because we don't want to emit the LHS as an expression.
if (op == tok_equal) {
auto LHSE = static_cast<VariableExpr *>(LHS.get());
if (!LHSE) {
errs() << "destination of '=' must be a variable.";
return nullptr;
}
Value *Val = RHS->codegen();
if (!Val)
return nullptr;
// Look up the name.
Value *Variable = Compiler::getInstance().getNamedValue(LHSE->getName());
if (!Variable) {
errs() << "Unknown Variable Name";
return nullptr;
}
Compiler::getInstance().StoreValueInVariable(Val, Variable);
return Val;
}
Value *L = LHS->codegen();
Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
switch (op) {
case tok_plus:
return Compiler::getInstance().emitAddition(L, R);
case tok_minus:
return Compiler::getInstance().emitSubtraction(L, R);
case tok_star:
return Compiler::getInstance().emitMultiplication(L, R);
case tok_slash:
return Compiler::getInstance().emitDivision(L, R);
case tok_less:
return Compiler::getInstance().emitLessThan(L, R);
case tok_greater:
return Compiler::getInstance().emitGreaterThan(L, R);
case tok_less_equal:
return Compiler::getInstance().emitLessThanOrEqual(L, R);
case tok_greater_equal:
return Compiler::getInstance().emitGreaterThanOrEqual(L, R);
case tok_equal_equal:
return Compiler::getInstance().emitEquality(L, R);
case tok_bang_equal:
return Compiler::getInstance().emitInequality(L, R);
default:
std::cout << "invalid binary operator";
return nullptr;
}
}
Value *CallExpr::codegen() {
// Look up the name in the global module table.
Function *CalleeF = Compiler::getInstance().getFunction(Callee);
if (!CalleeF) {
std::cout << "Unknown function referenced";
return nullptr;
}
// If argument mismatch error.
if (CalleeF->arg_size() != Args.size()) {
std::cout << "Incorrect # arguments passed";
return nullptr;
}
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
return Compiler::getInstance().emitCall(CalleeF, ArgsV, "calltmp");
}
llvm::Value *ForExpr::codegen() {
return Compiler::getInstance().emitForLoop(VarName, std::move(Start),
std::move(End), std::move(Step),
std::move(Body));
}
Function *PrototypeAST::codegen() {
return Compiler::getInstance().emitPrototype(Name, Args);
}
Function *FunctionAST::codegen() {
// First, check for an existing function from a previous 'extern' declaration.
Function *func =
Compiler::getInstance().checkFunctionExists(Proto->getName());
if (!func)
func = Proto->codegen();
if (!func) {
std::cout << "Failed To creat function prototype";
return nullptr;
}
if (!func->empty()) {
std::cout << "Function cannot be redefined.";
return (Function *)nullptr;
}
return Compiler::getInstance().emitFunction(func, std::move(Body));
}
llvm::Value *UnaryExpr::codegen() {
// TODO:Add other tokenTypes here when we start supporting other data types
// that have other operators
auto L = LHS->codegen();
switch (op.getType()) {
case tok_minus:
return Compiler::getInstance().emitNegation(L);
}
}
llvm::Value *Block::codegen() {
Value *finalVal = nullptr;
for (auto const &expr : expressions) {
finalVal = expr->codegen();
if (!finalVal) {
errs() << "Failed To generate expression in a block";
return nullptr;
}
}
return finalVal;
}
llvm::Value *IfExpr::codegen() {
Value *PhiNode = Compiler::getInstance().emitIfThenElse(
std::move(Cond), std::move(Then), std::move(Else));
if (!PhiNode) {
std::cout << "Failed to generate condition";
return nullptr;
}
return PhiNode;
}