Add static allocator

This commit is contained in:
Sofia 2026-04-27 23:04:12 +03:00
parent 226118bcbb
commit bf87aa8c08
6 changed files with 146 additions and 0 deletions

View File

@ -25,6 +25,7 @@ add_executable(${PROJECT_NAME}
src/typechecker.cpp src/typechecker.cpp
src/binops.cpp src/binops.cpp
src/casting.cpp src/casting.cpp
src/stack_allocator.cpp
) )
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Weffc++ -Wextra -Wpedantic -Werror) target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Weffc++ -Wextra -Wpedantic -Werror)

View File

@ -10,6 +10,7 @@
#include "binops.h" #include "binops.h"
#include "tokens.h" #include "tokens.h"
#include "typechecker.h" #include "typechecker.h"
#include "stack_allocator.h"
namespace AST { namespace AST {
class Node { class Node {
@ -25,6 +26,7 @@ namespace AST {
public: public:
Expression(token::Metadata meta) : Node{ meta } {} Expression(token::Metadata meta) : Node{ meta } {}
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) = 0;
virtual void codegen_alloca(codegen::StackAllocator& allocator) = 0;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) = 0; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) = 0;
virtual void typecheck_preprocess(typecheck::Scope& scope) = 0; virtual void typecheck_preprocess(typecheck::Scope& scope) = 0;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -38,6 +40,7 @@ namespace AST {
public: public:
Statement(token::Metadata meta) : Node{ meta } {} Statement(token::Metadata meta) : Node{ meta } {}
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; 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_preprocess(typecheck::Scope& scope) = 0;
virtual void typecheck(typecheck::State& state, 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 ~IntLiteralExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -76,6 +80,7 @@ namespace AST {
virtual ~StringLiteralExpression() override = default; virtual ~StringLiteralExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -94,6 +99,7 @@ namespace AST {
virtual ~ValueReferenceExpression() override = default; virtual ~ValueReferenceExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -123,6 +129,7 @@ namespace AST {
virtual ~BinaryOperationExpression() override = default; virtual ~BinaryOperationExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -149,6 +156,7 @@ namespace AST {
virtual ~FunctionCallExpression() override = default; virtual ~FunctionCallExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -175,6 +183,7 @@ namespace AST {
virtual ~CastExpression() override = default; virtual ~CastExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -198,6 +207,7 @@ namespace AST {
virtual ~RefExpression() override = default; virtual ~RefExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -221,6 +231,7 @@ namespace AST {
virtual ~DerefExpression() override = default; virtual ~DerefExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -247,6 +258,7 @@ namespace AST {
virtual ~IndexAccessExpression() override = default; virtual ~IndexAccessExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -273,6 +285,7 @@ namespace AST {
virtual ~FieldAccessExpression() override = default; virtual ~FieldAccessExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -299,6 +312,7 @@ namespace AST {
virtual ~ListInitializerExpression() override = default; virtual ~ListInitializerExpression() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void codegen_alloca(codegen::StackAllocator& allocator) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual void typecheck_preprocess(typecheck::Scope& scope) override; virtual void typecheck_preprocess(typecheck::Scope& scope) override;
virtual typecheck::ExpressionType typecheck( virtual typecheck::ExpressionType typecheck(
@ -319,6 +333,7 @@ namespace AST {
virtual ~ReturnStatement() override = default; virtual ~ReturnStatement() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) 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_preprocess(typecheck::Scope& scope) override;
virtual void typecheck(typecheck::State& state, 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 ~InitializationStatement() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) 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_preprocess(typecheck::Scope& scope) override;
virtual void typecheck(typecheck::State& state, 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 ~ExpressionStatement() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) 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_preprocess(typecheck::Scope& scope) override;
virtual void typecheck(typecheck::State& state, 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 ~IfStatement() override = default;
virtual std::string formatted() override; virtual std::string formatted() override;
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) 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_preprocess(typecheck::Scope& scope) override;
virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override; virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override;
}; };

View File

@ -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) { for (auto& statement : *this->m_statements) {
statement->codegen(builder, inner_scope); statement->codegen(builder, inner_scope);
} }

92
src/stack_allocator.cpp Normal file
View File

@ -0,0 +1,92 @@
#include "stack_allocator.h"
#include "ast.h"
namespace codegen {
void StackAllocator::push_alloca(std::shared_ptr<types::Type> 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<llvm::Value*, std::shared_ptr<types::Type>>{ value, ty });
}
llvm::Value* StackAllocator::pop_alloca(std::shared_ptr<types::Type> 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);
}
}
}

28
src/stack_allocator.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <vector>
#include <llvm/IR/IRBuilder.h>
#include "types.h"
#include "builder.h"
namespace codegen {
class StackAllocator {
private:
std::vector<std::pair<llvm::Value*, std::shared_ptr<types::Type>>> 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<types::Type> ty, std::string name);
llvm::Value* pop_alloca(std::shared_ptr<types::Type> ty);
};
}
#endif

0
tokei Normal file
View File