diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 318 |
1 files changed, 22 insertions, 296 deletions
@@ -3,281 +3,34 @@ #include <iostream> #include <list> #include <map> -#include <memory> -#include <set> #include <string> #include <string_view> #include <tuple> -#include <llvm/ADT/APInt.h> -#include <llvm/IR/Constants.h> -#include <llvm/IR/IRBuilder.h> -#include <llvm/IR/LLVMContext.h> -#include <llvm/IR/Module.h> -#include <llvm/IR/Type.h> -#include <llvm/IR/DerivedTypes.h> +#include "ast.hpp" +#include "llvm.hpp" +#include "parser.hpp" +#include "var.hpp" -static std::unique_ptr<llvm::LLVMContext> llvmContext; -static std::unique_ptr<llvm::Module> llvmModule; -static std::unique_ptr<llvm::IRBuilder<>> llvmBuilder; -static llvm::Constant *llvmSp; -static llvm::Constant *llvmStack; - -struct Var { - llvm::Value *value; - bool callable; - - Var(llvm::Value *v = nullptr, bool c = false): value(v), callable(c) {} -}; -static std::list<std::map<std::string, Var>> llvmVars; - -Var llvmVarGet(const std::string& name, int skip = 0) { - for (auto sc = llvmVars.rbegin(); sc != llvmVars.rend(); ++sc) { - if (skip > 0) { - --skip; - continue; - } - if (sc->contains(name)) - return (*sc)[name]; - } - - return {}; -} - -struct BaseAST -{ - std::string name; - - BaseAST(const std::string& n): name(n) {} - - virtual ~BaseAST() = default; - - virtual llvm::Value *codegen() const { return nullptr; } -}; - -struct NumberAST : public BaseAST -{ - // push number onto stack - - explicit NumberAST(const std::string& n): BaseAST(n) {} - - llvm::Value *codegen() const override { - auto inttype = llvm::Type::getInt32Ty(*llvmContext); - auto stacktype = llvm::VectorType::get(inttype, 12, false); - auto dspval = llvmBuilder->CreateLoad(inttype, llvmSp); - auto one = llvm::ConstantInt::get(inttype, 1); - auto zero = llvm::ConstantInt::get(inttype, 0); - auto inc = llvmBuilder->CreateAdd(dspval, one); - llvmBuilder->CreateStore(inc, llvmSp, false); - - auto dsget = llvmBuilder->CreateGEP(stacktype, llvmStack, {zero, dspval}); - - auto val = llvm::ConstantInt::get(*llvmContext, llvm::APInt(32, std::stoi(name), true)); - return llvmBuilder->CreateStore(val, dsget); - } -}; - -struct PushAST : public BaseAST -{ - // push named value to stack - - explicit PushAST(const std::string& n): BaseAST(n) {} - - llvm::Value *codegen() const override { - if (auto [var, thunk] = llvmVarGet(name); var) { - auto inttype = llvm::Type::getInt32Ty(*llvmContext); - auto stacktype = llvm::VectorType::get(inttype, 12, false); - auto dspval = llvmBuilder->CreateLoad(inttype, llvmSp); - auto one = llvm::ConstantInt::get(inttype, 1); - auto zero = llvm::ConstantInt::get(inttype, 0); - auto inc = llvmBuilder->CreateAdd(dspval, one); - llvmBuilder->CreateStore(inc, llvmSp, false); - - auto dsget = llvmBuilder->CreateGEP(stacktype, llvmStack, {zero, dspval}); - - if (!thunk) - var = llvmBuilder->CreateLoad(inttype, var); - return llvmBuilder->CreateStore(var, dsget); - } else { - return nullptr; - } - } -}; - -struct PopAST : public BaseAST -{ - // pop value on stack to named var - - explicit PopAST(const std::string& n): BaseAST(n) {} - - llvm::Value *codegen() const override { - auto inttype = llvm::Type::getInt32Ty(*llvmContext); - auto stacktype = llvm::VectorType::get(inttype, 12, false); - auto one = llvm::ConstantInt::get(inttype, 1); - auto zero = llvm::ConstantInt::get(inttype, 0); - auto dspval = llvmBuilder->CreateLoad(inttype, llvmSp); - auto dec = llvmBuilder->CreateSub(dspval, one); - auto gep = llvmBuilder->CreateGEP(stacktype, llvmStack, {zero, dec}); - llvmBuilder->CreateStore(dec, llvmSp, false); - - auto var = new llvm::GlobalVariable(*llvmModule, inttype, false, llvm::GlobalValue::InternalLinkage, zero, name); - llvmBuilder->CreateStore(llvmBuilder->CreateLoad(inttype, gep), var, false); - - auto [it, _] = llvmVars.back().emplace(name, var); - return it->second.value; - } -}; - -struct CallAST : public BaseAST -{ - // invoke named invocable - - explicit CallAST(const std::string& n): BaseAST(n) {} - - llvm::Value *codegen() const override { - auto ftype = llvm::FunctionType::get(llvm::Type::getVoidTy(*llvmContext), {}, false); - - if (auto [var, call] = llvmVarGet(name); var) { - if (call) { - return llvmBuilder->CreateCall(ftype, var); - } else { - auto inttype = llvm::Type::getInt32Ty(*llvmContext); - auto val = llvmBuilder->CreateLoad(inttype, var); - auto cast = llvmBuilder->CreateIntToPtr(val, inttype->getPointerTo()); - return llvmBuilder->CreateCall(ftype, cast); - } - } else { - auto func = llvm::Function::Create(ftype, llvm::Function::ExternalLinkage, name, llvmModule.get()); - llvmVars.front().emplace(name, Var {func, true}); - return llvmBuilder->CreateCall(ftype, func); - } - } -}; - -struct ThunkAST : public BaseAST -{ - static int tcount; - - std::list<std::unique_ptr<BaseAST>> body; - llvm::IRBuilderBase::InsertPoint parent; - llvm::Function *func; - - explicit ThunkAST(): ThunkAST(std::string("__t") + std::to_string(tcount++)) {} - - explicit ThunkAST(std::string n): BaseAST(n) { - parent = llvmBuilder->saveIP(); - auto ftype = llvm::FunctionType::get(llvm::Type::getVoidTy(*llvmContext), {}, false); - func = llvm::Function::Create(ftype, llvm::Function::ExternalLinkage, name.c_str(), llvmModule.get()); - auto BB = llvm::BasicBlock::Create(*llvmContext, "entry", func); - llvmBuilder->SetInsertPoint(BB); - } - - llvm::Value *codegen() const override { - llvmBuilder->CreateRetVoid(); - llvmBuilder->restoreIP(parent); - - return func; - } -}; -int ThunkAST::tcount = 0; - -enum class Token { - none, - ThunkOpen, - ThunkClose, - Quote, - PopVar, - PushVar, - Var, - Number -}; - -static std::string name; +static LLVMState llvmState; static std::list<ThunkAST> scope; -bool isname(char ch) { - return !isspace(ch) && ch != ')'; -} - -std::string_view extractName(std::string_view sv) -{ - name.clear(); - - while (!sv.empty()) { - const auto ch = sv.front(); +static bool parseString(std::string_view sv); - if (isname(ch)) { - name += ch; - sv.remove_prefix(1); - } else { - break; - } - } - - return sv; -} - -std::pair<std::string_view, Token> nextToken(std::string_view sv) +int main() { - if (sv.empty()) - return {sv, Token::none}; - - while (std::isspace(sv.front())) - sv.remove_prefix(1); + Var::pushScope(); - if (sv.empty()) - return {sv, Token::none}; - - const auto ch = sv.front(); - if (ch == ';') { - return {{}, Token::none}; - } else if (ch == '(') { - return {sv.substr(1), Token::ThunkOpen}; - } else if (ch == ')') { - return {sv.substr(1), Token::ThunkClose}; - } else if (ch == '\'') { - return {extractName(sv.substr(1)), Token::Quote}; - } else if (ch == '$') { - return {extractName(sv.substr(1)), Token::PopVar}; - } else if (ch == '^') { - return {extractName(sv.substr(1)), Token::PushVar}; - } else if (isdigit(ch) || (ch == '-' && sv.size() > 1 && isdigit(sv[1]))) { - return {extractName(sv), Token::Number}; - } else if (isname(ch)) { - return {extractName(sv), Token::Var}; + std::string line; + while (std::cin.good()) { + std::getline(std::cin, line); + parseString(line); + //std::cout << std::endl; } - return {sv, Token::none}; -} + llvmState.output(); -void printToken(Token tok) -{ - switch (tok) { - case Token::ThunkOpen: - std::cout << "ThunkOpen "; - break; - case Token::ThunkClose: - std::cout << "ThunkClose "; - break; - case Token::Quote: - std::cout << "Quote "; - break; - case Token::PopVar: - std::cout << "PopVar "; - break; - case Token::PushVar: - std::cout << "PushVar "; - break; - case Token::Var: - std::cout << "Var "; - break; - case Token::Number: - std::cout << "Number "; - break; - case Token::none: - //std::cout << "none "; - break; - } + std::cout << std::endl; } bool parseString(std::string_view sv) @@ -296,17 +49,17 @@ bool parseString(std::string_view sv) switch (tok) { case Token::ThunkOpen: if (scope.empty()) - scope.emplace_back("main"); + scope.emplace_back(llvmState, "main"); else - scope.emplace_back(); - llvmVars.emplace_back(); + scope.emplace_back(llvmState); + Var::pushScope(); break; case Token::ThunkClose: { auto& thunk = scope.back(); - auto gen = thunk.codegen(); - llvmVars.pop_back(); - llvmVars.back().emplace(thunk.name, Var {gen, true}); + auto gen = thunk.codegen(llvmState); + Var::popScope(); + Var::addLocal(thunk.name, Var {gen, true}); expr.reset(new PushAST {thunk.name}); scope.pop_back(); } @@ -330,7 +83,7 @@ bool parseString(std::string_view sv) } if (expr && !scope.empty()) { - expr->codegen(); + expr->codegen(llvmState); //scope.back().body.emplace_back().swap(expr); } } @@ -341,30 +94,3 @@ bool parseString(std::string_view sv) return true; } -int main() -{ - llvmContext = std::make_unique<llvm::LLVMContext>(); - llvmModule = std::make_unique<llvm::Module>("forsp", *llvmContext); - llvmBuilder = std::make_unique<llvm::IRBuilder<>>(*llvmContext); - auto inttype = llvm::Type::getInt32Ty(*llvmContext); - auto stacktype = llvm::VectorType::get(inttype, 12, false); - auto zero = llvm::ConstantInt::get(inttype, 0); - auto zerovec = llvm::ConstantVector::get(llvm::ArrayRef(dynamic_cast<llvm::Constant *>(zero))); - llvmStack = new llvm::GlobalVariable(*llvmModule, stacktype, false, llvm::GlobalValue::ExternalLinkage, zerovec, "stack"); - llvmSp = new llvm::GlobalVariable(*llvmModule, inttype, false, llvm::GlobalValue::ExternalLinkage, zero, "sp"); - - llvmVars.emplace_back(); - - std::string line; - while (std::cin.good()) { - std::getline(std::cin, line); - parseString(line); - //std::cout << std::endl; - } - - //std::cout << "LLVM:" << std::endl; - llvmModule->print(llvm::errs(), nullptr); - - std::cout << std::endl; -} - |