aboutsummaryrefslogtreecommitdiffstats
path: root/ast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ast.cpp')
-rw-r--r--ast.cpp133
1 files changed, 102 insertions, 31 deletions
diff --git a/ast.cpp b/ast.cpp
index a528cc3..c7a9309 100644
--- a/ast.cpp
+++ b/ast.cpp
@@ -20,7 +20,24 @@
#include <charconv>
#include <iostream>
+extern std::list<ThunkAST> scope;
+
int ThunkAST::tcount = 0;
+int ThunkAST::envidx = 0;
+
+static inline auto loadEnv(LLVMState& llvmState, llvm::Value *index)
+{
+ auto ptrty = llvmState.inttype->getPointerTo();
+ auto gep = llvmState.builder.CreateGEP(ptrty, scope.back().env, {index});
+ return llvmState.builder.CreateLoad(ptrty, gep);
+}
+
+static inline auto storeEnv(LLVMState& llvmState, llvm::Value *index, llvm::Value *val)
+{
+ auto ptrty = llvmState.inttype->getPointerTo();
+ auto var = llvmState.builder.CreateGEP(ptrty, scope.back().env, {index});
+ return llvmState.builder.CreateStore(val, var, false);
+}
NumberAST::NumberAST(const std::string& n): BaseAST(n) {}
@@ -34,7 +51,7 @@ llvm::Value *NumberAST::codegen(LLVMState& llvmState) const
return nullptr;
} else {
auto val = llvmState.createInt(value);
- return llvmState.builder.CreateStore(val, llvmState.createPush());
+ return llvmState.createPush(val);
}
}
@@ -42,12 +59,16 @@ PushAST::PushAST(const std::string& n): BaseAST(n) {}
llvm::Value *PushAST::codegen(LLVMState& llvmState) const
{
- if (auto [var, thunk] = Var::lookup(name); var) {
- auto dsget = llvmState.createPush();
- if (!thunk)
- var = llvmState.builder.CreateLoad(llvmState.inttype, var);
+ if (auto [var, native] = Var::lookup(name, 1); var) {
+ auto index = llvm::ConstantInt::get(llvmState.inttype, ThunkAST::envidx++);
+ Var::addLocal(name, index);
+ }
+
+ if (auto [var, native] = Var::lookupLocal(name); var) {
+ if (!native)
+ var = loadEnv(llvmState, var);
- return llvmState.builder.CreateStore(var, dsget);
+ return llvmState.createPush(var);
} else {
std::cerr << "error: not defined: " << name << std::endl;
return nullptr;
@@ -58,42 +79,77 @@ PopAST::PopAST(const std::string& n): BaseAST(n) {}
llvm::Value *PopAST::codegen(LLVMState& llvmState) const
{
+ Var v;
+
if (name == "self") {
- extern std::list<ThunkAST> scope;
- auto func = scope.back().func;
- auto var = llvmState.createVariable(name);
- llvmState.builder.CreateStore(func, var, false);
- return Var::addLocal(name, var).value;
+ v = {scope.back().func, true};
} else {
- auto gep = llvmState.createPop();
- auto var = llvmState.createVariable(name);
- auto load = llvmState.builder.CreateLoad(llvmState.inttype, gep);
- llvmState.builder.CreateStore(load, var, false);
+ auto index = llvm::ConstantInt::get(llvmState.inttype, ThunkAST::envidx++);
+ auto pop = llvmState.createPop();
+ storeEnv(llvmState, index, pop);
- return Var::addLocal(name, var).value;
+ v = index;
}
+
+ return Var::addLocal(name, v).value;
}
CallAST::CallAST(const std::string& n): BaseAST(n) {}
llvm::Value *CallAST::codegen(LLVMState& llvmState) const
{
- if (auto [var, call] = Var::lookup(name); var) {
- if (call) {
- return llvmState.builder.CreateCall(llvmState.ftype, var);
- } else {
- auto val = llvmState.builder.CreateLoad(llvmState.inttype, var);
- auto cast = llvmState.builder.CreateIntToPtr(val,
- llvmState.inttype->getPointerTo());
- return llvmState.builder.CreateCall(llvmState.ftype, cast);
- }
+ if (auto [var, native] = Var::lookup(name, 1); var && !native) {
+ auto index = llvm::ConstantInt::get(llvmState.inttype, ThunkAST::envidx++);
+ Var::addLocal(name, index);
+ }
+
+ llvm::Value *fn;
+ if (auto [var, native] = Var::lookup(name); var) {
+ if (!native)
+ var = loadEnv(llvmState, var);
+
+ fn = var;
} else {
std::cerr << "warning: anticipating external function: "
<< name << std::endl;
- auto func = llvmState.createFunction(name);
- Var::addGlobal(name, Var {func, true});
- return llvmState.builder.CreateCall(llvmState.ftype, func);
+
+ fn = llvmState.createFunction(name);
+ Var::addGlobal(name, Var {fn, true});
+ }
+
+ auto ptrty = llvmState.inttype->getPointerTo();
+ llvm::Type *type;
+ llvm::Value *mem;
+
+ if (auto sz = Var::vars.back().size(); sz > 0) {
+ type = llvm::VectorType::get(llvmState.inttype, sz, false);
+ mem = llvmState.builder.CreateAlloca(type, nullptr);
+
+ int i = 0;
+ for (auto& [_, v] : Var::vars.back()) {
+ if (!v.native) {
+ auto index = llvm::ConstantInt::get(llvmState.inttype, i++);
+ auto m = llvmState.builder.CreateGEP(ptrty, mem, {index});
+ llvmState.builder.CreateStore(loadEnv(llvmState, v.value), m, false);
+ }
+ }
+ }
+
+ auto call = llvmState.builder.CreateCall(llvmState.ftype, fn, llvm::ArrayRef {scope.back().env});
+
+ if (auto sz = Var::vars.back().size(); sz > 0) {
+ int i = 0;
+ for (auto& [_, v] : Var::vars.back()) {
+ if (!v.native) {
+ auto index = llvm::ConstantInt::get(llvmState.inttype, i++);
+ auto m = llvmState.builder.CreateGEP(ptrty, mem, {index});
+ auto l = llvmState.builder.CreateLoad(ptrty, m);
+ storeEnv(llvmState, v.value, l);
+ }
+ }
}
+
+ return call;
}
ThunkAST::ThunkAST(LLVMState& llvmState):
@@ -103,15 +159,30 @@ ThunkAST::ThunkAST(LLVMState& llvmState, std::string n): BaseAST(n)
{
parent = llvmState.builder.saveIP();
func = llvmState.createFunction(name);
- auto BB = llvmState.createEntry(func);
- llvmState.builder.SetInsertPoint(BB);
+ entry = llvmState.createEntry(func);
+ body = llvm::BasicBlock::Create(llvmState.ctx, "body", func);
+ env = func->getArg(0);
+
+ llvmState.builder.SetInsertPoint(entry);
+ llvmState.builder.SetInsertPoint(body);
}
llvm::Value *ThunkAST::codegen(LLVMState& llvmState) const
{
llvmState.builder.CreateRetVoid();
- llvmState.builder.restoreIP(parent);
+ llvmState.builder.SetInsertPoint(entry);
+
+ if (Var::vars.back().size() > 0) {
+ for (auto& [n, v] : Var::vars.back()) {
+ if (auto [c, _] = Var::lookup(n, 1); c) {
+ auto src = loadEnv(llvmState, c);
+ storeEnv(llvmState, v.value, src);
+ }
+ }
+ }
+ llvmState.builder.CreateBr(body);
+ llvmState.builder.restoreIP(parent);
return func;
}