mirror of
https://github.com/PashaBibko/LX.git
synced 2026-04-04 01:49:05 +00:00
IT CRASHES
WHYYYYYYYYYYYYYYYYYYYYYY
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<EnableASAN>false</EnableASAN>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
|||||||
11
Main.cpp
11
Main.cpp
@@ -55,6 +55,12 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
// Turns the tokens into an AST
|
// Turns the tokens into an AST
|
||||||
LX::FileAST AST = LX::TurnTokensIntoAbstractSyntaxTree(tokens, log.get());
|
LX::FileAST AST = LX::TurnTokensIntoAbstractSyntaxTree(tokens, log.get());
|
||||||
|
|
||||||
|
// Turns the AST into something
|
||||||
|
LX::GenerateIR(AST);
|
||||||
|
|
||||||
|
// Returns success
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (LX::IncorrectCommandLineArgs)
|
catch (LX::IncorrectCommandLineArgs)
|
||||||
@@ -104,6 +110,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
// -1 means an error slipped through (IDK how, it's here just in case)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,9 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\AST-Constructors.cpp" />
|
||||||
|
<ClCompile Include="src\AST-LLVM.cpp" />
|
||||||
|
<ClCompile Include="src\GenIR.cpp" />
|
||||||
<ClCompile Include="src\Parser.cpp" />
|
<ClCompile Include="src\Parser.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
|||||||
@@ -14,5 +14,14 @@
|
|||||||
<ClCompile Include="src\Parser.cpp">
|
<ClCompile Include="src\Parser.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\AST-LLVM.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\AST-Constructors.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\GenIR.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
16
Parser/src/AST-Constructors.cpp
Normal file
16
Parser/src/AST-Constructors.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <Parser.h>
|
||||||
|
|
||||||
|
namespace LX::AST
|
||||||
|
{
|
||||||
|
NumberLiteral::NumberLiteral(std::string num)
|
||||||
|
: Node(Node::NUMBER_LITERAL), m_Number(num)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Operation::Operation(std::unique_ptr<Node> lhs, Token::TokenType op, std::unique_ptr<Node> rhs)
|
||||||
|
: Node(Node::OPERATION), m_Lhs(std::move(lhs)), m_Operand(op), m_Rhs(std::move(rhs))
|
||||||
|
{}
|
||||||
|
|
||||||
|
ReturnStatement::ReturnStatement(std::unique_ptr<Node> val)
|
||||||
|
: Node(Node::RETURN_STATEMENT), m_Val(std::move(val))
|
||||||
|
{}
|
||||||
|
}
|
||||||
54
Parser/src/AST-LLVM.cpp
Normal file
54
Parser/src/AST-LLVM.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include <Parser.h>
|
||||||
|
|
||||||
|
#include <LLVM.h>
|
||||||
|
#include <Util.h>
|
||||||
|
|
||||||
|
namespace LX::AST
|
||||||
|
{
|
||||||
|
llvm::Value* NumberLiteral::GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
||||||
|
{
|
||||||
|
// Converts the string to it's int equivalent
|
||||||
|
// Will eventually need to do floating point stuff here as well
|
||||||
|
int number = std::stoi(m_Number);
|
||||||
|
|
||||||
|
// Returns it as a llvm value (if valid)
|
||||||
|
llvm::Value* out = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), number, true);
|
||||||
|
ThrowIf<IRGenerationError>(out == nullptr);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* Operation::GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
||||||
|
{
|
||||||
|
// Gets the IR for both sides of the operation
|
||||||
|
llvm::Value* lhs = m_Lhs->GenIR(context, module, builder);
|
||||||
|
llvm::Value* rhs = m_Rhs->GenIR(context, module, builder);
|
||||||
|
|
||||||
|
// If either side is null then return null to prevent invalid IR //
|
||||||
|
if (lhs == nullptr || rhs == nullptr)
|
||||||
|
{
|
||||||
|
ThrowIf<IRGenerationError>(true);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will eventually get the correct operator but for now everything is add
|
||||||
|
llvm::Value* out = builder.CreateAdd(lhs, rhs);
|
||||||
|
ThrowIf<IRGenerationError>(out == nullptr);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value* ReturnStatement::GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
||||||
|
{
|
||||||
|
if (m_Val == nullptr)
|
||||||
|
{
|
||||||
|
ThrowIf<IRGenerationError>(true);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
llvm::Value* out = builder.CreateRet(m_Val->GenIR(context, module, builder));
|
||||||
|
ThrowIf<IRGenerationError>(out == nullptr);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
Parser/src/GenIR.cpp
Normal file
64
Parser/src/GenIR.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#include <Parser.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace LX
|
||||||
|
{
|
||||||
|
void GenerateIR(FileAST& ast)
|
||||||
|
{
|
||||||
|
// Generates stuff //
|
||||||
|
|
||||||
|
llvm::LLVMContext context;
|
||||||
|
llvm::IRBuilder<> builder(context);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_ptr<llvm::Module> module = std::make_unique<llvm::Module>("add_ints", context);
|
||||||
|
|
||||||
|
// Defines main function //
|
||||||
|
|
||||||
|
llvm::FunctionType* funcType = llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false);
|
||||||
|
llvm::Function* mainFunc = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main", module.get());
|
||||||
|
llvm::BasicBlock* entry = llvm::BasicBlock::Create(context, "entry", mainFunc);
|
||||||
|
builder.SetInsertPoint(entry);
|
||||||
|
|
||||||
|
// Loops over AST to generate IR //
|
||||||
|
|
||||||
|
for (auto& node : ast.functions[0].body)
|
||||||
|
{
|
||||||
|
switch (node->m_Type)
|
||||||
|
{
|
||||||
|
case AST::Node::RETURN_STATEMENT:
|
||||||
|
{
|
||||||
|
node->GenIR(context, *module, builder);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->getTerminator() == nullptr)
|
||||||
|
{
|
||||||
|
builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verification of the IR //
|
||||||
|
|
||||||
|
if (llvm::verifyFunction(*mainFunc, &llvm::errs()) || llvm::verifyModule(*module, &llvm::errs()))
|
||||||
|
{
|
||||||
|
std::cerr << "Error: IR generation failed" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outputs the IR to the console //
|
||||||
|
|
||||||
|
module->print(llvm::outs(), nullptr);
|
||||||
|
|
||||||
|
} // <- Crashes here
|
||||||
|
|
||||||
|
std::cout << "Finished generating IR" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
||||||
Started lexing file
|
|
||||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
||||||
|
|
||||||
Token::FUNCTION
|
|
||||||
Token::IDENTIFIER: main
|
|
||||||
Unknown: 3
|
|
||||||
Token::NUMBER_LITERAL: 34
|
|
||||||
Token::ADD
|
|
||||||
Token::NUMBER_LITERAL: 4324
|
|
||||||
|
|
||||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
||||||
Started parsing tokens
|
|
||||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
||||||
|
|
||||||
AST length: 1
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
func main
|
func main
|
||||||
return 34 + 4324
|
return 3 + 4
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// Helper file for including all neccesarry parts of LLVM //
|
// Helper file for including all neccesarry parts of LLVM //
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
// Disables all warnings as LLVM files have a lot of Data-loss casts that won't cause issues //
|
// Disables all warnings as LLVM files have a lot of Data-loss casts that won't cause issues //
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
// Lexer foward declares fstream components so we can use them here //
|
// Lexer foward declares fstream components so we can use them here //
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
|
#include <LLVM.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
// Foward declares all items of the llvm lib that we need //
|
// Foward declares all items of the llvm lib that we need //
|
||||||
// Done to avoid including LLVM.h to shorten compile times //
|
// Done to avoid including LLVM.h to shorten compile times //
|
||||||
|
/*
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
class Value;
|
class Value;
|
||||||
@@ -18,7 +20,7 @@ namespace llvm
|
|||||||
|
|
||||||
template<typename T1 = ConstantFolder, typename T2 = IRBuilderDefaultInserter>
|
template<typename T1 = ConstantFolder, typename T2 = IRBuilderDefaultInserter>
|
||||||
class IRBuilder;
|
class IRBuilder;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// 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
|
||||||
@@ -65,14 +67,11 @@ namespace LX::AST
|
|||||||
class NumberLiteral : public Node
|
class NumberLiteral : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NumberLiteral(std::string num)
|
// Constructor to set values and automatically set type
|
||||||
: Node(Node::NUMBER_LITERAL), m_Number(num)
|
NumberLiteral(std::string num);
|
||||||
{}
|
|
||||||
|
|
||||||
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
{
|
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) override;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The number it stores
|
// The number it stores
|
||||||
@@ -85,14 +84,11 @@ namespace LX::AST
|
|||||||
class Operation : public Node
|
class Operation : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Operation(std::unique_ptr<Node> lhs, Token::TokenType op, std::unique_ptr<Node> rhs)
|
// Constructor to set values and automatically set type
|
||||||
: Node(Node::OPERATION), m_Lhs(std::move(lhs)), m_Operand(op), m_Rhs(std::move(rhs))
|
Operation(std::unique_ptr<Node> lhs, Token::TokenType op, std::unique_ptr<Node> rhs);
|
||||||
{}
|
|
||||||
|
|
||||||
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
{
|
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) override;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The sides of the operation
|
// The sides of the operation
|
||||||
@@ -107,14 +103,11 @@ namespace LX::AST
|
|||||||
class ReturnStatement : public Node
|
class ReturnStatement : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ReturnStatement(std::unique_ptr<Node> val)
|
// Constructor to set values and automatically set type
|
||||||
: Node(Node::RETURN_STATEMENT), m_Val(std::move(val))
|
ReturnStatement(std::unique_ptr<Node> val);
|
||||||
{}
|
|
||||||
|
|
||||||
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
|
// Function for generating LLVN IR (Intermediate representation) //
|
||||||
{
|
llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) override;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// What it is returning (can be null)
|
// What it is returning (can be null)
|
||||||
@@ -124,6 +117,8 @@ namespace LX::AST
|
|||||||
|
|
||||||
namespace LX
|
namespace LX
|
||||||
{
|
{
|
||||||
|
struct IRGenerationError {};
|
||||||
|
|
||||||
struct FunctionDefinition
|
struct FunctionDefinition
|
||||||
{
|
{
|
||||||
FunctionDefinition()
|
FunctionDefinition()
|
||||||
@@ -143,4 +138,6 @@ namespace LX
|
|||||||
};
|
};
|
||||||
|
|
||||||
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log);
|
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector<Token>& tokens, std::ofstream* log);
|
||||||
|
|
||||||
|
void GenerateIR(FileAST& ast);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user