diff options
Diffstat (limited to 'ast.cpp')
-rw-r--r-- | ast.cpp | 133 |
1 files changed, 102 insertions, 31 deletions
@@ -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; } |