From 14b2b36748f6b19593f0b4bf8abb8cf81c97dfde Mon Sep 17 00:00:00 2001
From: Pasha Bibko <156938226+PashaBibko@users.noreply.github.com>
Date: Thu, 17 Apr 2025 18:34:56 +0100
Subject: [PATCH] IT CRASHES
WHYYYYYYYYYYYYYYYYYYYYYY
---
LX-LLVM.vcxproj | 1 +
Main.cpp | 11 ++++--
Parser/Parser.vcxproj | 3 ++
Parser/Parser.vcxproj.filters | 9 +++++
Parser/src/AST-Constructors.cpp | 16 +++++++++
Parser/src/AST-LLVM.cpp | 54 ++++++++++++++++++++++++++++
Parser/src/GenIR.cpp | 64 +++++++++++++++++++++++++++++++++
build-test/Log.txt | 17 ---------
build-test/main.lx | 2 +-
common/LLVM.h | 2 +-
common/Parser.h | 41 ++++++++++-----------
11 files changed, 177 insertions(+), 43 deletions(-)
create mode 100644 Parser/src/AST-Constructors.cpp
create mode 100644 Parser/src/AST-LLVM.cpp
create mode 100644 Parser/src/GenIR.cpp
diff --git a/LX-LLVM.vcxproj b/LX-LLVM.vcxproj
index 68cec45..1fb1e60 100644
--- a/LX-LLVM.vcxproj
+++ b/LX-LLVM.vcxproj
@@ -45,6 +45,7 @@
true
v143
Unicode
+ false
Application
diff --git a/Main.cpp b/Main.cpp
index 9b6f741..e0d91ef 100644
--- a/Main.cpp
+++ b/Main.cpp
@@ -55,6 +55,12 @@ int main(int argc, char** argv)
// Turns the tokens into an AST
LX::FileAST AST = LX::TurnTokensIntoAbstractSyntaxTree(tokens, log.get());
+
+ // Turns the AST into something
+ LX::GenerateIR(AST);
+
+ // Returns success
+ return 0;
}
catch (LX::IncorrectCommandLineArgs)
@@ -104,6 +110,7 @@ int main(int argc, char** argv)
return 6;
}
-
- return 0;
+
+ // -1 means an error slipped through (IDK how, it's here just in case)
+ return -1;
}
diff --git a/Parser/Parser.vcxproj b/Parser/Parser.vcxproj
index e594b2a..c5ffbbe 100644
--- a/Parser/Parser.vcxproj
+++ b/Parser/Parser.vcxproj
@@ -131,6 +131,9 @@
+
+
+
diff --git a/Parser/Parser.vcxproj.filters b/Parser/Parser.vcxproj.filters
index 23540ae..9159eb8 100644
--- a/Parser/Parser.vcxproj.filters
+++ b/Parser/Parser.vcxproj.filters
@@ -14,5 +14,14 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
\ No newline at end of file
diff --git a/Parser/src/AST-Constructors.cpp b/Parser/src/AST-Constructors.cpp
new file mode 100644
index 0000000..60200bf
--- /dev/null
+++ b/Parser/src/AST-Constructors.cpp
@@ -0,0 +1,16 @@
+#include
+
+namespace LX::AST
+{
+ NumberLiteral::NumberLiteral(std::string num)
+ : Node(Node::NUMBER_LITERAL), m_Number(num)
+ {}
+
+ Operation::Operation(std::unique_ptr lhs, Token::TokenType op, std::unique_ptr rhs)
+ : Node(Node::OPERATION), m_Lhs(std::move(lhs)), m_Operand(op), m_Rhs(std::move(rhs))
+ {}
+
+ ReturnStatement::ReturnStatement(std::unique_ptr val)
+ : Node(Node::RETURN_STATEMENT), m_Val(std::move(val))
+ {}
+}
diff --git a/Parser/src/AST-LLVM.cpp b/Parser/src/AST-LLVM.cpp
new file mode 100644
index 0000000..0ba3f17
--- /dev/null
+++ b/Parser/src/AST-LLVM.cpp
@@ -0,0 +1,54 @@
+#include
+
+#include
+#include
+
+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(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(true);
+ return nullptr;
+ }
+
+ // Will eventually get the correct operator but for now everything is add
+ llvm::Value* out = builder.CreateAdd(lhs, rhs);
+ ThrowIf(out == nullptr);
+ return out;
+ }
+
+ llvm::Value* ReturnStatement::GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
+ {
+ if (m_Val == nullptr)
+ {
+ ThrowIf(true);
+ return nullptr;
+ }
+
+ else
+ {
+ llvm::Value* out = builder.CreateRet(m_Val->GenIR(context, module, builder));
+ ThrowIf(out == nullptr);
+ return out;
+ }
+ }
+}
diff --git a/Parser/src/GenIR.cpp b/Parser/src/GenIR.cpp
new file mode 100644
index 0000000..ae8d646
--- /dev/null
+++ b/Parser/src/GenIR.cpp
@@ -0,0 +1,64 @@
+#include
+
+#include
+
+namespace LX
+{
+ void GenerateIR(FileAST& ast)
+ {
+ // Generates stuff //
+
+ llvm::LLVMContext context;
+ llvm::IRBuilder<> builder(context);
+
+ {
+ std::unique_ptr module = std::make_unique("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;
+ }
+}
diff --git a/build-test/Log.txt b/build-test/Log.txt
index a060136..e69de29 100644
--- a/build-test/Log.txt
+++ b/build-test/Log.txt
@@ -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
diff --git a/build-test/main.lx b/build-test/main.lx
index 538eb44..fd50a1a 100644
--- a/build-test/main.lx
+++ b/build-test/main.lx
@@ -1,2 +1,2 @@
func main
- return 34 + 4324
+ return 3 + 4
diff --git a/common/LLVM.h b/common/LLVM.h
index 6999738..bccd7cc 100644
--- a/common/LLVM.h
+++ b/common/LLVM.h
@@ -2,7 +2,7 @@
// Helper file for including all neccesarry parts of LLVM //
#ifdef _MSC_VER
-
+
// Disables all warnings as LLVM files have a lot of Data-loss casts that won't cause issues //
#pragma warning(push)
#pragma warning(disable : 4244)
diff --git a/common/Parser.h b/common/Parser.h
index 62dcbf3..1d62caf 100644
--- a/common/Parser.h
+++ b/common/Parser.h
@@ -2,11 +2,13 @@
// Lexer foward declares fstream components so we can use them here //
#include
+#include
#include
// Foward declares all items of the llvm lib that we need //
// Done to avoid including LLVM.h to shorten compile times //
+/*
namespace llvm
{
class Value;
@@ -18,7 +20,7 @@ namespace llvm
template
class IRBuilder;
-}
+}*/
// The nodes of the abstract syntax tree constructed by the parser from the tokens //
namespace LX::AST
@@ -65,14 +67,11 @@ namespace LX::AST
class NumberLiteral : public Node
{
public:
- NumberLiteral(std::string num)
- : Node(Node::NUMBER_LITERAL), m_Number(num)
- {}
+ // Constructor to set values and automatically set type
+ NumberLiteral(std::string num);
- llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
- {
- return nullptr;
- }
+ // Function for generating LLVN IR (Intermediate representation) //
+ llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) override;
private:
// The number it stores
@@ -85,14 +84,11 @@ namespace LX::AST
class Operation : public Node
{
public:
- Operation(std::unique_ptr lhs, Token::TokenType op, std::unique_ptr rhs)
- : Node(Node::OPERATION), m_Lhs(std::move(lhs)), m_Operand(op), m_Rhs(std::move(rhs))
- {}
+ // Constructor to set values and automatically set type
+ Operation(std::unique_ptr lhs, Token::TokenType op, std::unique_ptr rhs);
- llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
- {
- return nullptr;
- }
+ // Function for generating LLVN IR (Intermediate representation) //
+ llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) override;
private:
// The sides of the operation
@@ -107,14 +103,11 @@ namespace LX::AST
class ReturnStatement : public Node
{
public:
- ReturnStatement(std::unique_ptr val)
- : Node(Node::RETURN_STATEMENT), m_Val(std::move(val))
- {}
+ // Constructor to set values and automatically set type
+ ReturnStatement(std::unique_ptr val);
- llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder)
- {
- return nullptr;
- }
+ // Function for generating LLVN IR (Intermediate representation) //
+ llvm::Value* GenIR(llvm::LLVMContext& context, llvm::Module& module, llvm::IRBuilder<>& builder) override;
private:
// What it is returning (can be null)
@@ -124,6 +117,8 @@ namespace LX::AST
namespace LX
{
+ struct IRGenerationError {};
+
struct FunctionDefinition
{
FunctionDefinition()
@@ -143,4 +138,6 @@ namespace LX
};
FileAST TurnTokensIntoAbstractSyntaxTree(std::vector& tokens, std::ofstream* log);
+
+ void GenerateIR(FileAST& ast);
}