/** * forspll - LLVM-based Forsp compiler * Copyright (C) 2024 Clyne Sullivan * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include "llvm.hpp" LLVMState::LLVMState(): ctx(), modul("forsp", ctx), builder(ctx), inttype(llvm::Type::getInt64Ty(ctx)), stacktype(llvm::VectorType::get(inttype, 16, false)), ftype(llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), llvm::ArrayRef {inttype->getPointerTo()}, false)), one(llvm::ConstantInt::get(inttype, 1)), zero(llvm::ConstantInt::get(inttype, 0)) { auto zerovec = llvm::ConstantVector::get(llvm::ArrayRef(zero)); llvmSp = new llvm::GlobalVariable(modul, inttype, false, llvm::GlobalValue::ExternalLinkage, zero, "sp"); llvmStack = new llvm::GlobalVariable(modul, stacktype, false, llvm::GlobalValue::ExternalLinkage, zerovec, "stack"); } llvm::Value *LLVMState::createPush(llvm::Value *var) { auto dspval = builder.CreateLoad(inttype, llvmSp); auto inc = builder.CreateAdd(dspval, one); builder.CreateStore(inc, llvmSp); auto gep = builder.CreateGEP(stacktype, llvmStack, {zero, dspval}); return builder.CreateStore(var, gep); } llvm::Value *LLVMState::createPop() { auto dspval = builder.CreateLoad(inttype, llvmSp); auto dec = builder.CreateSub(dspval, one); builder.CreateStore(dec, llvmSp); auto gep = builder.CreateGEP(stacktype, llvmStack, {zero, dec}); return builder.CreateLoad(inttype, gep); } llvm::Function *LLVMState::createFunction(const std::string& name) { auto func = llvm::Function::Create(ftype, llvm::Function::ExternalLinkage, name.c_str(), modul); func->getArg(0)->setName("penv"); return func; } llvm::BasicBlock *LLVMState::createEntry(llvm::Function *func) { return llvm::BasicBlock::Create(ctx, "entry", func); } llvm::Value *LLVMState::createVariable(const std::string& name) { return new llvm::GlobalVariable(modul, inttype, false, llvm::GlobalValue::InternalLinkage, zero, name); } llvm::Constant *LLVMState::createInt(int n) { return llvm::ConstantInt::get(ctx, llvm::APInt(64, n, true)); } void LLVMState::output() { modul.print(llvm::outs(), nullptr); }