-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcodegen.h
129 lines (112 loc) · 3.47 KB
/
codegen.h
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
#ifndef CODEGEN_H
#define CODEGEN_H
#include <llvm/IR/Value.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <map>
#include "ASTnode.h"
#include "typefactor.h"
extern std::string errmsg;
struct CodegenBlock {
llvm::BasicBlock* block;
};
struct Var{
llvm::Value* value;
bool isArray;
std::vector<llvm::Value*>* arraydims;
llvm::Type* arraytype;
Var(llvm::Value* v, bool a=0, const std::vector<llvm::Value*>* dims=nullptr, llvm::Type* t=nullptr) {
value = v;
isArray = a;
arraydims = isArray ? new std::vector<llvm::Value*>(*dims) : nullptr;
arraytype = t;
}
};
struct CodegenNamespace {
std::map<std::string, Var*> localvars;
};
struct CodegenFunction {
llvm::Function* function;
llvm::Value* retval;
llvm::BasicBlock* retblk;
CodegenFunction(llvm::Function* f, llvm::Value* v, llvm::BasicBlock* b) {
function = f;
retval = v;
retblk = b;
}
};
struct CodegenContext{
llvm::LLVMContext llvmContext;
llvm::IRBuilder<> builder;
llvm::Module* module;
CodegenFunction curfunc;
std::vector<CodegenBlock*> blockStack;
std::vector<CodegenNamespace*> nameStack;
CodegenContext() :builder(llvmContext), curfunc(nullptr, nullptr, nullptr) {
module = new llvm::Module("main", llvmContext);
}
llvm::BasicBlock* currentBlock() {
return blockStack.size() ? blockStack.back()->block : nullptr;
}
void pushBlock(llvm::BasicBlock* blk) {
CodegenBlock* cblk = new CodegenBlock;
cblk->block = blk;
blockStack.push_back(cblk);
builder.SetInsertPoint(blk);
}
void popBlock() {
blockStack.pop_back();
builder.SetInsertPoint(currentBlock());
}
llvm::Function* currentFunction() {
return curfunc.function;
}
bool isGlobal() {
return currentFunction() == nullptr;
}
void pushNamespace() {
nameStack.push_back(new CodegenNamespace);
}
void popNamespace() {
delete nameStack.back();
nameStack.pop_back();
}
llvm::Value* getLocalSymbol(std::string s) {
EXCEPT_RET(nameStack.back()->localvars.count(s), nullptr);
return nameStack.back()->localvars[s]->value;
}
void addLocalSymbol(std::string s, llvm::Value* v) {
nameStack.back()->localvars[s] = new Var(v);
}
void addLocalSymbol(std::string s, Var* v) {
nameStack.back()->localvars[s] = v;
}
llvm::Value* getSymbol(std::string s) {
for(int i=nameStack.size()-1; ~i; i--) {
if(nameStack[i]->localvars.count(s))
return nameStack[i]->localvars[s]->value;
}
return nullptr;
}
std::vector<llvm::Value*>* getSymbolArrayDim(std::string s) {
for(int i=nameStack.size()-1; ~i; i--) {
if(nameStack[i]->localvars.count(s)) {
EXCEPT_RET(nameStack[i]->localvars[s]->isArray, nullptr);
return nameStack[i]->localvars[s]->arraydims;
}
}
return nullptr;
}
llvm::Type* getSymbolArrayType(std::string s) {
for(int i=nameStack.size()-1; ~i; i--) {
if(nameStack[i]->localvars.count(s)) {
EXCEPT_RET(nameStack[i]->localvars[s]->isArray, nullptr);
return nameStack[i]->localvars[s]->arraytype;
}
}
return nullptr;
}
};
int GenerateCode(CodegenContext &context, ASTnode* root);
#endif