Files
MIRROR-LX-OriginalRepo/Parser/src/AST-LLVM.cpp
2025-05-05 17:17:33 +01:00

127 lines
3.5 KiB
C++

#include <LX-Common.h>
#include <Parser.h>
#include <AST.h>
namespace LX::AST
{
// Function for genrating LLVM IR (Intermediate representation), will throw an error if called on this class //
llvm::Value* MultiNode::GenIR(InfoLLVM & LLVM)
{
throw int(); // <- TODO: Make an error type
}
// Function for generating LLVM IR (Intermediate representation) //
llvm::Value* NumberLiteral::GenIR(InfoLLVM& LLVM)
{
// Converts the string to it's int equivalent //
// TODO: Support floating point values //
int number = std::stoi(m_Number);
// Returns it as a llvm value (if valid) //
// TODO: Support floating point values //
// TODO: Make the error actually output information //
llvm::Value* out = llvm::ConstantInt::get(llvm::Type::getInt32Ty(LLVM.context), number, true);
ThrowIf<IRGenerationError>(out == nullptr);
return out;
}
// Function for generating LLVM IR (Intermediate representation) //
llvm::Value* Operation::GenIR(InfoLLVM& LLVM)
{
// Generates the IR for both sides of the operation //
llvm::Value* lhs = m_Lhs->GenIR(LLVM);
llvm::Value* rhs = m_Rhs->GenIR(LLVM);
// If either side is null then return null to prevent invalid IR //
// TODO: Make the error actually output information //
if (lhs == nullptr || rhs == nullptr)
{
ThrowIf<IRGenerationError>(true);
return nullptr;
}
// Generates the IR of the operation //
llvm::Value* out = nullptr;
// Creates the correct operation depending on the operand //
switch (m_Operand)
{
case Token::ADD:
out = LLVM.builder.CreateAdd(lhs, rhs);
break;
case Token::SUB:
out = LLVM.builder.CreateSub(lhs, rhs);
break;
case Token::MUL:
out = LLVM.builder.CreateMul(lhs, rhs);
break;
case Token::DIV:
out = LLVM.builder.CreateSDiv(lhs, rhs);
break;
default:
// TODO: Add an error here
out = nullptr;
}
// Checks it all went succesfully before returning //
ThrowIf<IRGenerationError>(out == nullptr);
return out;
}
// Function for generating LLVM IR (Intermediate representation) //
llvm::Value* ReturnStatement::GenIR(InfoLLVM& LLVM)
{
// Checks if it is a void return //
if (m_Val == nullptr)
{
// Void returns are currently not implemented //
// TODO: Find out how to return nothing from a function //
ThrowIf<IRGenerationError>(true);
return nullptr;
}
// Else it will be returning a value //
else
{
// Generates the value and creates a return for it //
// TODO: Make the error actually output information //
llvm::Value* out = LLVM.builder.CreateRet(m_Val->GenIR(LLVM));
ThrowIf<IRGenerationError>(out == nullptr);
return out;
}
}
// Function for generating LLVM IR (Intermediate representation) //
llvm::Value* VariableDeclaration::GenIR(InfoLLVM& LLVM)
{
// Creates the variable within the scope //
return LLVM.scope->CreateVar(m_Name, LLVM);
}
llvm::Value* VariableAssignment::GenIR(InfoLLVM& LLVM)
{
// Gets the variable from the current scope //
llvm::AllocaInst* asignee = LLVM.scope->GetVar(m_Name);
ThrowIf<Scope::VariableDoesntExist>(asignee == nullptr);
// Creates the assignment //
return LLVM.builder.CreateStore(m_Value->GenIR(LLVM), asignee);
}
llvm::Value* VariableAccess::GenIR(InfoLLVM& LLVM)
{
// Loads the variable from the current scope //
llvm::AllocaInst* var = LLVM.scope->GetVar(m_Name);
ThrowIf<Scope::VariableDoesntExist>(var == nullptr);
// Creates the load within the AST //
return LLVM.builder.CreateLoad(llvm::Type::getInt32Ty(LLVM.context), var, m_Name + "_val");
}
}