From bf87aa8c086bd24826188c33dabc9bc3897262a4 Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 27 Apr 2026 23:04:12 +0300 Subject: [PATCH] Add static allocator --- CMakeLists.txt | 1 + src/ast.h | 18 ++++++++ src/codegen.cpp | 7 ++++ src/stack_allocator.cpp | 92 +++++++++++++++++++++++++++++++++++++++++ src/stack_allocator.h | 28 +++++++++++++ tokei | 0 6 files changed, 146 insertions(+) create mode 100644 src/stack_allocator.cpp create mode 100644 src/stack_allocator.h create mode 100644 tokei diff --git a/CMakeLists.txt b/CMakeLists.txt index ab26fb0..123ce97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(${PROJECT_NAME} src/typechecker.cpp src/binops.cpp src/casting.cpp + src/stack_allocator.cpp ) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Weffc++ -Wextra -Wpedantic -Werror) diff --git a/src/ast.h b/src/ast.h index 8296517..9446a7d 100644 --- a/src/ast.h +++ b/src/ast.h @@ -10,6 +10,7 @@ #include "binops.h" #include "tokens.h" #include "typechecker.h" +#include "stack_allocator.h" namespace AST { class Node { @@ -25,6 +26,7 @@ namespace AST { public: Expression(token::Metadata meta) : Node{ meta } {} virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; + virtual void codegen_alloca(codegen::StackAllocator& allocator) = 0; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) = 0; virtual void typecheck_preprocess(typecheck::Scope& scope) = 0; virtual typecheck::ExpressionType typecheck( @@ -38,6 +40,7 @@ namespace AST { public: Statement(token::Metadata meta) : Node{ meta } {} virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; + virtual void codegen_alloca(codegen::StackAllocator& allocator) = 0; virtual void typecheck_preprocess(typecheck::Scope& scope) = 0; virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) = 0; }; @@ -58,6 +61,7 @@ namespace AST { virtual ~IntLiteralExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -76,6 +80,7 @@ namespace AST { virtual ~StringLiteralExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -94,6 +99,7 @@ namespace AST { virtual ~ValueReferenceExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -123,6 +129,7 @@ namespace AST { virtual ~BinaryOperationExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -149,6 +156,7 @@ namespace AST { virtual ~FunctionCallExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -175,6 +183,7 @@ namespace AST { virtual ~CastExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -198,6 +207,7 @@ namespace AST { virtual ~RefExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -221,6 +231,7 @@ namespace AST { virtual ~DerefExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -247,6 +258,7 @@ namespace AST { virtual ~IndexAccessExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -273,6 +285,7 @@ namespace AST { virtual ~FieldAccessExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -299,6 +312,7 @@ namespace AST { virtual ~ListInitializerExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual typecheck::ExpressionType typecheck( @@ -319,6 +333,7 @@ namespace AST { virtual ~ReturnStatement() override = default; virtual std::string formatted() override; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; }; @@ -342,6 +357,7 @@ namespace AST { virtual ~InitializationStatement() override = default; virtual std::string formatted() override; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; }; @@ -356,6 +372,7 @@ namespace AST { virtual ~ExpressionStatement() override = default; virtual std::string formatted() override; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; }; @@ -378,6 +395,7 @@ namespace AST { virtual ~IfStatement() override = default; virtual std::string formatted() override; virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual void codegen_alloca(codegen::StackAllocator& allocator) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; }; diff --git a/src/codegen.cpp b/src/codegen.cpp index 7c9f557..66b5b45 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -597,6 +597,13 @@ namespace AST { } } + codegen::StackAllocator allocator{ builder, scope.structs }; + + builder.builder->SetInsertPoint(BB); + for (auto& statement : *this->m_statements) { + statement->codegen_alloca(allocator); + } + for (auto& statement : *this->m_statements) { statement->codegen(builder, inner_scope); } diff --git a/src/stack_allocator.cpp b/src/stack_allocator.cpp new file mode 100644 index 0000000..c11a06a --- /dev/null +++ b/src/stack_allocator.cpp @@ -0,0 +1,92 @@ + +#include "stack_allocator.h" +#include "ast.h" + +namespace codegen { + void StackAllocator::push_alloca(std::shared_ptr ty, std::string name) { + auto type = ty->codegen(this->m_builder, this->m_structs); + auto value = this->m_builder.builder->CreateAlloca(type, nullptr, name); + this->m_stack_ptrs.push_back(std::pair>{ value, ty }); + } + + llvm::Value* StackAllocator::pop_alloca(std::shared_ptr ty) { + assert(this->m_stack_ptrs.size() > 0); + auto first = this->m_stack_ptrs[0]; + assert(types::types_equal(first.second, ty)); + this->m_stack_ptrs.erase(this->m_stack_ptrs.begin()); + return first.first; + } +} + +namespace AST { + void IntLiteralExpression::codegen_alloca(codegen::StackAllocator&) { + } + + void StringLiteralExpression::codegen_alloca(codegen::StackAllocator&) { + } + + void ValueReferenceExpression::codegen_alloca(codegen::StackAllocator&) { + } + + void BinaryOperationExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_lhs->codegen_alloca(allocator); + this->m_rhs->codegen_alloca(allocator); + } + + void FunctionCallExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_fn_expr->codegen_alloca(allocator); + for (auto& arg : this->m_args) { + arg->codegen_alloca(allocator); + } + } + + void CastExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void RefExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void DerefExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void IndexAccessExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void FieldAccessExpression::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void ListInitializerExpression::codegen_alloca(codegen::StackAllocator& allocator) { + allocator.push_alloca(this->m_ty, "list"); + for (auto& expr : this->m_expressions) { + expr->codegen_alloca(allocator); + } + } + + void ReturnStatement::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void InitializationStatement::codegen_alloca(codegen::StackAllocator& allocator) { + if (this->m_expr) { + (*this->m_expr)->codegen_alloca(allocator); + } + allocator.push_alloca(this->m_type, this->m_name); + } + + void ExpressionStatement::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_expr->codegen_alloca(allocator); + } + + void IfStatement::codegen_alloca(codegen::StackAllocator& allocator) { + this->m_condition->codegen_alloca(allocator); + this->m_then->codegen_alloca(allocator); + if (this->m_else) { + (*this->m_else)->codegen_alloca(allocator); + } + } +} \ No newline at end of file diff --git a/src/stack_allocator.h b/src/stack_allocator.h new file mode 100644 index 0000000..5a697ab --- /dev/null +++ b/src/stack_allocator.h @@ -0,0 +1,28 @@ + +#ifndef ALLOCATOR_H +#define ALLOCATOR_H + +#include +#include + +#include "types.h" +#include "builder.h" + +namespace codegen { + class StackAllocator { + private: + std::vector>> m_stack_ptrs; + codegen::Builder& m_builder; + codegen::TypeMap& m_structs; + public: + StackAllocator(codegen::Builder& builder, codegen::TypeMap& structs) + : m_stack_ptrs{} + , m_builder{ builder } + , m_structs{ structs } { + } + void push_alloca(std::shared_ptr ty, std::string name); + llvm::Value* pop_alloca(std::shared_ptr ty); + }; +} + +#endif \ No newline at end of file diff --git a/tokei b/tokei new file mode 100644 index 0000000..e69de29