mirror of
https://github.com/PashaBibko/LX.git
synced 2026-04-04 01:49:05 +00:00
Function parameters can now be read
This commit is contained in:
@@ -6,7 +6,11 @@
|
|||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
|
|
||||||
// Foward declares the wrapper around the LLVM objects we need to pass around //
|
// Foward declares the wrapper around the LLVM objects we need to pass around //
|
||||||
namespace LX { struct InfoLLVM; }
|
namespace LX
|
||||||
|
{
|
||||||
|
struct InfoLLVM;
|
||||||
|
class FunctionScope;
|
||||||
|
}
|
||||||
|
|
||||||
// The nodes of the abstract syntax tree constructed by the parser from the tokens //
|
// The nodes of the abstract syntax tree constructed by the parser from the tokens //
|
||||||
namespace LX::AST
|
namespace LX::AST
|
||||||
@@ -48,7 +52,7 @@ namespace LX::AST
|
|||||||
virtual ~Node() = default;
|
virtual ~Node() = default;
|
||||||
|
|
||||||
// Function for generating LLVN IR (Intermediate representation) //
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
virtual llvm::Value* GenIR(InfoLLVM& LLVM) = 0;
|
virtual llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) = 0;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
virtual void Log(unsigned depth) = 0;
|
virtual void Log(unsigned depth) = 0;
|
||||||
|
|||||||
@@ -153,11 +153,13 @@
|
|||||||
<ClCompile Include="src\GenIR.cpp" />
|
<ClCompile Include="src\GenIR.cpp" />
|
||||||
<ClCompile Include="src\Parser.cpp" />
|
<ClCompile Include="src\Parser.cpp" />
|
||||||
<ClCompile Include="src\ParserErrors.cpp" />
|
<ClCompile Include="src\ParserErrors.cpp" />
|
||||||
|
<ClCompile Include="src\Scope.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="inc\AST.h" />
|
<ClInclude Include="inc\AST.h" />
|
||||||
<ClInclude Include="inc\ParserErrors.h" />
|
<ClInclude Include="inc\ParserErrors.h" />
|
||||||
<ClInclude Include="inc\ParserInfo.h" />
|
<ClInclude Include="inc\ParserInfo.h" />
|
||||||
|
<ClInclude Include="inc\Scope.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
<ClCompile Include="src\AST\AST-Loggers.cpp">
|
<ClCompile Include="src\AST\AST-Loggers.cpp">
|
||||||
<Filter>Source Files\AST</Filter>
|
<Filter>Source Files\AST</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scope.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="inc\AST.h">
|
<ClInclude Include="inc\AST.h">
|
||||||
@@ -46,5 +49,8 @@
|
|||||||
<ClInclude Include="inc\ParserInfo.h">
|
<ClInclude Include="inc\ParserInfo.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="inc\Scope.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <LX-Common.h>
|
#include <LX-Common.h>
|
||||||
|
|
||||||
#include <Parser.h>
|
#include <Parser.h>
|
||||||
@@ -25,7 +27,7 @@ namespace LX::AST
|
|||||||
MultiNode();
|
MultiNode();
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation), will throw error if called on this class //
|
// Function for generating LLVM IR (Intermediate representation), will throw error if called on this class //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file, will throw an error if called on this class //
|
// Function to log the node to a file, will throw an error if called on this class //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
@@ -42,7 +44,7 @@ namespace LX::AST
|
|||||||
NumberLiteral(std::string num);
|
NumberLiteral(std::string num);
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
@@ -61,7 +63,7 @@ namespace LX::AST
|
|||||||
Operation(std::unique_ptr<Node> lhs, Token::TokenType op, std::unique_ptr<Node> rhs);
|
Operation(std::unique_ptr<Node> lhs, Token::TokenType op, std::unique_ptr<Node> rhs);
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
@@ -83,7 +85,7 @@ namespace LX::AST
|
|||||||
ReturnStatement(std::unique_ptr<Node> val);
|
ReturnStatement(std::unique_ptr<Node> val);
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
@@ -101,7 +103,7 @@ namespace LX::AST
|
|||||||
VariableDeclaration(const std::string& name);
|
VariableDeclaration(const std::string& name);
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
@@ -121,7 +123,7 @@ namespace LX::AST
|
|||||||
VariableAssignment(const std::string& name, std::unique_ptr<AST::Node> val);
|
VariableAssignment(const std::string& name, std::unique_ptr<AST::Node> val);
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
@@ -142,7 +144,7 @@ namespace LX::AST
|
|||||||
VariableAccess(const std::string& name);
|
VariableAccess(const std::string& name);
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* GenIR(InfoLLVM& LLVM) override;
|
llvm::Value* GenIR(InfoLLVM& LLVM, FunctionScope& func) override;
|
||||||
|
|
||||||
// Function to log the node to a file //
|
// Function to log the node to a file //
|
||||||
void Log(unsigned depth) override;
|
void Log(unsigned depth) override;
|
||||||
|
|||||||
104
Parser/inc/Scope.h
Normal file
104
Parser/inc/Scope.h
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LX-Common.h>
|
||||||
|
|
||||||
|
#include <AST.h>
|
||||||
|
|
||||||
|
namespace LX
|
||||||
|
{
|
||||||
|
CREATE_EMPTY_LX_ERROR_TYPE(VariableError);
|
||||||
|
|
||||||
|
class FunctionScope
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FunctionScope(const std::vector<std::string> paramNames, llvm::Function* func)
|
||||||
|
{
|
||||||
|
// Counter for the args //
|
||||||
|
unsigned argCounter = 0;
|
||||||
|
|
||||||
|
// Checks the parameter does not exist before inserting //
|
||||||
|
for (const std::string& param : paramNames)
|
||||||
|
{
|
||||||
|
ThrowIf<VariableError>(GetVarLocation(param) != NONE);
|
||||||
|
|
||||||
|
// Adds the argument to the map and sets its name //
|
||||||
|
m_Params[param] = func->getArg(argCounter);
|
||||||
|
m_Params[param]->setName(param);
|
||||||
|
|
||||||
|
// Iterates to the next one //
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* DecVar(const std::string& name, InfoLLVM& LLVM)
|
||||||
|
{
|
||||||
|
// Finds out if the variable already exists //
|
||||||
|
ThrowIf<VariableError>(GetVarLocation(name) != NONE);
|
||||||
|
|
||||||
|
// Allocates the variable and then returns a pointer to it's allocation //
|
||||||
|
llvm::AllocaInst* inst = LLVM.builder.CreateAlloca(LLVM.builder.getInt32Ty(), nullptr, name);
|
||||||
|
m_LocalVars[name] = inst;
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* AccessVar(const std::string& name, InfoLLVM& LLVM)
|
||||||
|
{
|
||||||
|
VariableLocation l = GetVarLocation(name);
|
||||||
|
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case LOCAL:
|
||||||
|
return LLVM.builder.CreateLoad(LLVM.builder.getInt32Ty(), m_LocalVars[name], name + "_v");
|
||||||
|
|
||||||
|
case PARAMS:
|
||||||
|
return m_Params[name];
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw VariableError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* AssignVar(const std::string& name, AST::Node* value, InfoLLVM& LLVM, FunctionScope& scope)
|
||||||
|
{
|
||||||
|
// Checks it is a local variable and not a parameter //
|
||||||
|
ThrowIf<VariableError>(GetVarLocation(name) != LOCAL);
|
||||||
|
|
||||||
|
// Returns a pointer to the assignment in the builder //
|
||||||
|
return LLVM.builder.CreateStore(value->GenIR(LLVM, scope), m_LocalVars[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum VariableLocation
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
PARAMS = 1,
|
||||||
|
LOCAL = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
VariableLocation GetVarLocation(const std::string& name)
|
||||||
|
{
|
||||||
|
// Searches in the variable maps //
|
||||||
|
auto pIt = m_Params.find(name);
|
||||||
|
auto lIt = m_LocalVars.find(name);
|
||||||
|
|
||||||
|
if (pIt != m_Params.end())
|
||||||
|
{
|
||||||
|
return PARAMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lIt != m_LocalVars.end())
|
||||||
|
{
|
||||||
|
return LOCAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Holds the parameters of the functions //
|
||||||
|
std::unordered_map<std::string, llvm::Argument*> m_Params;
|
||||||
|
|
||||||
|
// Holds all local variables //
|
||||||
|
std::unordered_map<std::string, llvm::AllocaInst*> m_LocalVars;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,18 +3,18 @@
|
|||||||
#include <Parser.h>
|
#include <Parser.h>
|
||||||
|
|
||||||
#include <ParserErrors.h>
|
#include <ParserErrors.h>
|
||||||
#include <AST.h>
|
#include <Scope.h>
|
||||||
|
|
||||||
namespace LX::AST
|
namespace LX::AST
|
||||||
{
|
{
|
||||||
// Function for genrating LLVM IR (Intermediate representation), will throw an error if called on this class //
|
// Function for genrating LLVM IR (Intermediate representation), will throw an error if called on this class //
|
||||||
llvm::Value* MultiNode::GenIR(InfoLLVM & LLVM)
|
llvm::Value* MultiNode::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
throw int(); // <- TODO: Make an error type
|
throw int(); // <- TODO: Make an error type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* NumberLiteral::GenIR(InfoLLVM& LLVM)
|
llvm::Value* NumberLiteral::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
// Converts the string to it's int equivalent //
|
// Converts the string to it's int equivalent //
|
||||||
// TODO: Support floating point values //
|
// TODO: Support floating point values //
|
||||||
@@ -29,11 +29,11 @@ namespace LX::AST
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* Operation::GenIR(InfoLLVM& LLVM)
|
llvm::Value* Operation::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
// Generates the IR for both sides of the operation //
|
// Generates the IR for both sides of the operation //
|
||||||
llvm::Value* lhs = m_Lhs->GenIR(LLVM);
|
llvm::Value* lhs = m_Lhs->GenIR(LLVM, func);
|
||||||
llvm::Value* rhs = m_Rhs->GenIR(LLVM);
|
llvm::Value* rhs = m_Rhs->GenIR(LLVM, func);
|
||||||
|
|
||||||
// If either side is null then return null to prevent invalid IR //
|
// If either side is null then return null to prevent invalid IR //
|
||||||
// TODO: Make the error actually output information //
|
// TODO: Make the error actually output information //
|
||||||
@@ -76,7 +76,7 @@ namespace LX::AST
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* ReturnStatement::GenIR(InfoLLVM& LLVM)
|
llvm::Value* ReturnStatement::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
// Checks if it is a void return //
|
// Checks if it is a void return //
|
||||||
if (m_Val == nullptr)
|
if (m_Val == nullptr)
|
||||||
@@ -92,25 +92,25 @@ namespace LX::AST
|
|||||||
{
|
{
|
||||||
// Generates the value and creates a return for it //
|
// Generates the value and creates a return for it //
|
||||||
// TODO: Make the error actually output information //
|
// TODO: Make the error actually output information //
|
||||||
llvm::Value* out = LLVM.builder.CreateRet(m_Val->GenIR(LLVM));
|
llvm::Value* out = LLVM.builder.CreateRet(m_Val->GenIR(LLVM, func));
|
||||||
ThrowIf<IRGenerationError>(out == nullptr);
|
ThrowIf<IRGenerationError>(out == nullptr);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function for generating LLVM IR (Intermediate representation) //
|
// Function for generating LLVM IR (Intermediate representation) //
|
||||||
llvm::Value* VariableDeclaration::GenIR(InfoLLVM& LLVM)
|
llvm::Value* VariableDeclaration::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return func.DecVar(m_Name, LLVM);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value* VariableAssignment::GenIR(InfoLLVM& LLVM)
|
llvm::Value* VariableAssignment::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return func.AssignVar(m_Name, m_Value.get(), LLVM, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value* VariableAccess::GenIR(InfoLLVM& LLVM)
|
llvm::Value* VariableAccess::GenIR(InfoLLVM& LLVM, FunctionScope& func)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return func.AccessVar(m_Name, LLVM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <Parser.h>
|
#include <Parser.h>
|
||||||
|
|
||||||
#include <ParserErrors.h>
|
#include <ParserErrors.h>
|
||||||
#include <AST.h>
|
#include <Scope.h>
|
||||||
|
|
||||||
namespace LX
|
namespace LX
|
||||||
{
|
{
|
||||||
@@ -32,22 +32,24 @@ namespace LX
|
|||||||
{
|
{
|
||||||
// Creates the functions signature and return type //
|
// Creates the functions signature and return type //
|
||||||
|
|
||||||
llvm::FunctionType* retType = llvm::FunctionType::get(llvm::Type::getInt32Ty(LLVM.context), false); // <- Defaults to int currently
|
std::cout << funcAST.params.size() << std::endl;
|
||||||
|
|
||||||
|
std::vector<llvm::Type*> funcParams(funcAST.params.size(), LLVM.builder.getInt32Ty());
|
||||||
|
|
||||||
|
llvm::FunctionType* retType = llvm::FunctionType::get(llvm::Type::getInt32Ty(LLVM.context), funcParams, false); // <- Defaults to int currently
|
||||||
llvm::Function* func = llvm::Function::Create(retType, GetLinkageType(funcAST.name), funcAST.name, LLVM.module);
|
llvm::Function* func = llvm::Function::Create(retType, GetLinkageType(funcAST.name), funcAST.name, LLVM.module);
|
||||||
llvm::BasicBlock* entry = llvm::BasicBlock::Create(LLVM.context, funcAST.name + "-entry", func);
|
llvm::BasicBlock* entry = llvm::BasicBlock::Create(LLVM.context, funcAST.name + "-entry", func);
|
||||||
LLVM.builder.SetInsertPoint(entry);
|
LLVM.builder.SetInsertPoint(entry);
|
||||||
|
|
||||||
// Adds the function's parameters to the scope //
|
// Creates the storer of the variables/parameters //
|
||||||
for (std::string& param : funcAST.params)
|
|
||||||
{
|
FunctionScope funcScope(funcAST.params, func);
|
||||||
//LLVM.scope->CreateVar(param, LLVM);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates the IR within the function by looping over the nodes //
|
// Generates the IR within the function by looping over the nodes //
|
||||||
for (auto& node : funcAST.body)
|
for (auto& node : funcAST.body)
|
||||||
{
|
{
|
||||||
ThrowIf<IRGenerationError>(IsValidTopLevelNode(node->m_Type) == false); // <- TODO: replace with actual error type
|
ThrowIf<IRGenerationError>(IsValidTopLevelNode(node->m_Type) == false); // <- TODO: replace with actual error type
|
||||||
node->GenIR(LLVM);
|
node->GenIR(LLVM, funcScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a terminator if there is none //
|
// Adds a terminator if there is none //
|
||||||
|
|||||||
17
Parser/src/Scope.cpp
Normal file
17
Parser/src/Scope.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include <LX-Common.h>
|
||||||
|
|
||||||
|
#include <Scope.h>
|
||||||
|
|
||||||
|
#include <AST.h>
|
||||||
|
|
||||||
|
namespace LX
|
||||||
|
{
|
||||||
|
const char* VariableError::ErrorType() const
|
||||||
|
{
|
||||||
|
return "Variable Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableError::PrintToConsole() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user