IT CRASHES

WHYYYYYYYYYYYYYYYYYYYYYY
This commit is contained in:
Pasha Bibko
2025-04-17 18:34:56 +01:00
parent 3017e70631
commit 14b2b36748
11 changed files with 177 additions and 43 deletions

View File

@@ -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>

View File

@@ -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)
@@ -105,5 +111,6 @@ 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;
} }

View File

@@ -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" />

View File

@@ -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>

View 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
View 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
View 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;
}
}

View File

@@ -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

View File

@@ -1,2 +1,2 @@
func main func main
return 34 + 4324 return 3 + 4

View File

@@ -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);
} }