|
|
|
/**
|
|
|
|
* forspll - LLVM-based Forsp compiler
|
|
|
|
* Copyright (C) 2024 Clyne Sullivan <clyne@bitgloo.com>
|
|
|
|
*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include "ast.hpp"
|
|
|
|
|
|
|
|
#include <charconv>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
int ThunkAST::tcount = 0;
|
|
|
|
|
|
|
|
NumberAST::NumberAST(const std::string& n): BaseAST(n) {}
|
|
|
|
|
|
|
|
llvm::Value *NumberAST::codegen(LLVMState& llvmState) const
|
|
|
|
{
|
|
|
|
int value;
|
|
|
|
auto [ptr, _] = std::from_chars(&name.front(), &name.back() + 1, value);
|
|
|
|
|
|
|
|
if (ptr <= &name.back()) {
|
|
|
|
std::cerr << "error: not a number: " << name << std::endl;
|
|
|
|
return nullptr;
|
|
|
|
} else {
|
|
|
|
auto val = llvmState.createInt(value);
|
|
|
|
return llvmState.builder.CreateStore(val, llvmState.createPush());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
return llvmState.builder.CreateStore(var, dsget);
|
|
|
|
} else {
|
|
|
|
std::cerr << "error: not defined: " << name << std::endl;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PopAST::PopAST(const std::string& n): BaseAST(n) {}
|
|
|
|
|
|
|
|
llvm::Value *PopAST::codegen(LLVMState& llvmState) const
|
|
|
|
{
|
|
|
|
auto gep = llvmState.createPop();
|
|
|
|
auto var = llvmState.createVariable(name);
|
|
|
|
auto load = llvmState.builder.CreateLoad(llvmState.inttype, gep);
|
|
|
|
llvmState.builder.CreateStore(load, var, false);
|
|
|
|
|
|
|
|
return Var::addLocal(name, var).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);
|
|
|
|
}
|
|
|
|
} 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ThunkAST::ThunkAST(LLVMState& llvmState):
|
|
|
|
ThunkAST(llvmState, std::string("__t") + std::to_string(tcount++)) {}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Value *ThunkAST::codegen(LLVMState& llvmState) const
|
|
|
|
{
|
|
|
|
llvmState.builder.CreateRetVoid();
|
|
|
|
llvmState.builder.restoreIP(parent);
|
|
|
|
|
|
|
|
return func;
|
|
|
|
}
|
|
|
|
|