aboutsummaryrefslogtreecommitdiffstats
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp318
1 files changed, 22 insertions, 296 deletions
diff --git a/main.cpp b/main.cpp
index e963340..50c0266 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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;
-}
-