From 0f201aa8c8aa24eb76a4ab562b38455171e2c556 Mon Sep 17 00:00:00 2001 From: Xircon Date: Sun, 2 Aug 2026 01:15:28 -0400 Subject: [PATCH] reshit my shit --- src/arena.hxx | 65 +++++++++++++++++------ src/generation.hxx | 119 +++++++++++++++++++++---------------------- src/main.cxx | 10 ++-- src/parser.hxx | 8 +-- src/tokenization.hxx | 2 +- 5 files changed, 120 insertions(+), 84 deletions(-) diff --git a/src/arena.hxx b/src/arena.hxx index 2ff6033..f659de1 100644 --- a/src/arena.hxx +++ b/src/arena.hxx @@ -1,29 +1,64 @@ #pragma once -#include -#include -#include +#include +#include +#include class ArenaAllocator { public: - inline explicit ArenaAllocator(size_t bytes) : m_size(bytes) { - m_buffer = static_cast(malloc(m_size)); - m_offset = m_buffer; + explicit ArenaAllocator(const size_t max_num_bytes) + : m_size { max_num_bytes } + , m_buffer { new std::byte[max_num_bytes] } + , m_offset { m_buffer } + { } - template - inline T* alloc() { - void* offset = m_offset; - m_offset += sizeof(T); - return static_cast(offset); + ArenaAllocator(const ArenaAllocator&) = delete; + ArenaAllocator& operator=(const ArenaAllocator&) = delete; + + ArenaAllocator(ArenaAllocator&& other) noexcept + : m_size { std::exchange(other.m_size, 0) } + , m_buffer { std::exchange(other.m_buffer, nullptr) } + , m_offset { std::exchange(other.m_offset, nullptr) } + { } - inline ArenaAllocator(const ArenaAllocator& other) = delete; + ArenaAllocator& operator=(ArenaAllocator&& other) noexcept + { + std::swap(m_size, other.m_size); + std::swap(m_buffer, other.m_buffer); + std::swap(m_offset, other.m_offset); + return *this; + } - inline ArenaAllocator operator=(const ArenaAllocator& other) = delete; + template + [[nodiscard]] T* alloc() + { + size_t remaining_num_bytes = m_size - static_cast(m_offset - m_buffer); + auto pointer = static_cast(m_offset); + const auto aligned_address = std::align(alignof(T), sizeof(T), pointer, remaining_num_bytes); + if (aligned_address == nullptr) { + throw std::bad_alloc {}; + } + m_offset = static_cast(aligned_address) + sizeof(T); + return static_cast(aligned_address); + } - inline ~ArenaAllocator() { - free(m_buffer); + template + [[nodiscard]] T* emplace(Args&&... args) + { + const auto allocated_memory = alloc(); + return new (allocated_memory) T { std::forward(args)... }; + } + + ~ArenaAllocator() + { + // No destructors are called for the stored objects. Thus, memory + // leaks are possible (e.g. when storing std::vector objects or + // other non-trivially destructable objects in the allocator). + // Although this could be changed, it would come with additional + // runtime overhead and therefore is not implemented. + delete[] m_buffer; } private: diff --git a/src/generation.hxx b/src/generation.hxx index d7a2a01..1235bb5 100644 --- a/src/generation.hxx +++ b/src/generation.hxx @@ -22,128 +22,127 @@ public: void gen_stmt(const node::Stmt* stmt) { struct StmtVisitor { // Visiting the homies - Generator* gen; + Generator& gen; void operator()(const node::StmtExit* stmt_exit) const { - gen->gen_expr(stmt_exit->expr); - gen->m_output << " mov rax, 60\n"; - gen->pop("rdi"); - gen->m_output << " syscall\n"; + gen.gen_expr(stmt_exit->expr); + gen.m_output << " mov rax, 60\n"; + gen.pop("rdi"); + gen.m_output << " syscall\n"; } void operator()(const node::StmtVar* stmt_var) { - auto it = std::find_if(gen->m_vars.cbegin(), gen->m_vars.cend(), [&](const Var& var){return var.name == stmt_var->ident.value.value();}); - if (it != gen->m_vars.cend()) { + if (std::ranges::find_if(gen.m_vars.cbegin(), gen.m_vars.cend(), [&](const Var& var){return var.name == stmt_var->ident.value.value();}) != gen.m_vars.cend()) { err::redefine(stmt_var->ident.value.value()); exit(EXIT_FAILURE); } - gen->m_vars.push_back({.name = stmt_var->ident.value.value(), .stack_loc = gen->m_stack_size}); - gen->gen_expr(stmt_var->expr); + gen.m_vars.push_back({.name = stmt_var->ident.value.value(), .stack_loc = gen.m_stack_size}); + gen.gen_expr(stmt_var->expr); } void operator()(const node::StmtIf* stmt_if) const { - gen->gen_expr(stmt_if->expr); - gen->pop("rax"); - std::string label = gen->create_label(); - gen->m_output << " test rax, rax\n"; - gen->m_output << " jz " << label << "\n"; - gen->gen_scope(stmt_if->scope); - gen->m_output << "\n" << label << ":\n"; + gen.gen_expr(stmt_if->expr); + gen.pop("rax"); + const std::string label = gen.create_label(); + gen.m_output << " test rax, rax\n"; + gen.m_output << " jz " << label << "\n"; + gen.gen_scope(stmt_if->scope); + gen.m_output << "\n" << label << ":\n"; } void operator()(const node::Scope* scope) { - gen->gen_scope(scope); + gen.gen_scope(scope); } }; - StmtVisitor visitor {.gen = this}; + StmtVisitor visitor {.gen = *this}; std::visit(visitor, stmt->var); } void gen_term(const node::Term* term) { struct TermVisitor { - Generator* gen; + Generator& gen; void operator()(const node::TermIntLit* term_int_lit) const { - gen->m_output << " mov rax, " << term_int_lit->int_lit.value.value() << "\n"; - gen->push("rax"); + gen.m_output << " mov rax, " << term_int_lit->int_lit.value.value() << "\n"; + gen.push("rax"); } void operator()(const node::TermIdent* term_ident) const { - auto it = std::find_if(gen->m_vars.cbegin(), gen->m_vars.cend(), [&](const Var& var){return var.name == term_ident->ident.value.value();}); - if (it == gen->m_vars.cend()) { + const auto it = std::ranges::find_if(gen.m_vars.cbegin(), gen.m_vars.cend(), [&](const Var& var){return var.name == term_ident->ident.value.value();}); + if (it == gen.m_vars.cend()) { err::undeclared(term_ident->ident.value.value()); exit(EXIT_FAILURE); } std::stringstream offset; - offset << "QWORD [rsp + " << (gen->m_stack_size - (*it).stack_loc - 1) * 8 << "]"; - gen->push(offset.str()); + offset << "QWORD [rsp + " << (gen.m_stack_size - it->stack_loc - 1) * 8 << "]"; + gen.push(offset.str()); } void operator()(const node::TermParen* term_paren) const { - gen->gen_expr(term_paren->expr); + gen.gen_expr(term_paren->expr); } }; - TermVisitor visitor ({.gen = this}); + TermVisitor visitor ({.gen = *this}); std::visit(visitor, term->var); } void gen_bin_expr(const node::BinExpr* bin_expr) { struct BinExprVisitor { - Generator* gen; + Generator& gen; void operator()(const node::BinExprAdd* add) { - gen->gen_expr(add->rhs); - gen->gen_expr(add->lhs); - gen->pop("rax"); - gen->pop("rbx"); - gen->m_output << " add rax, rbx\n"; - gen->push("rax"); + gen.gen_expr(add->rhs); + gen.gen_expr(add->lhs); + gen.pop("rax"); + gen.pop("rbx"); + gen.m_output << " add rax, rbx\n"; + gen.push("rax"); } void operator()(const node::BinExprMul* mul) { - gen->gen_expr(mul->rhs); - gen->gen_expr(mul->lhs); - gen->pop("rax"); - gen->pop("rbx"); - gen->m_output << " mul rbx\n"; - gen->push("rax"); + gen.gen_expr(mul->rhs); + gen.gen_expr(mul->lhs); + gen.pop("rax"); + gen.pop("rbx"); + gen.m_output << " mul rbx\n"; + gen.push("rax"); } void operator()(const node::BinExprSub* sub) { - gen->gen_expr(sub->rhs); - gen->gen_expr(sub->lhs); - gen->pop("rax"); - gen->pop("rbx"); - gen->m_output << " sub rax, rbx\n"; - gen->push("rax"); + gen.gen_expr(sub->rhs); + gen.gen_expr(sub->lhs); + gen.pop("rax"); + gen.pop("rbx"); + gen.m_output << " sub rax, rbx\n"; + gen.push("rax"); } void operator()(const node::BinExprDiv* div) { - gen->gen_expr(div->rhs); - gen->gen_expr(div->lhs); - gen->pop("rax"); - gen->pop("rbx"); - gen->m_output << " div rbx\n"; - gen->push("rax"); + gen.gen_expr(div->rhs); + gen.gen_expr(div->lhs); + gen.pop("rax"); + gen.pop("rbx"); + gen.m_output << " div rbx\n"; + gen.push("rax"); } }; - BinExprVisitor visitor {.gen = this}; + BinExprVisitor visitor {.gen = *this}; std::visit(visitor, bin_expr->var); } void gen_expr(const node::Expr* expr) { struct ExprVisitor { - Generator* gen; + Generator& gen; void operator()(const node::Term* term) const { - gen->gen_term(term); + gen.gen_term(term); } void operator()(const node::BinExpr* bin_expr) const { - gen->gen_bin_expr(bin_expr); + gen.gen_bin_expr(bin_expr); } }; - ExprVisitor visitor {.gen = this}; + ExprVisitor visitor {.gen = *this}; std::visit(visitor, expr->var); } @@ -166,7 +165,7 @@ private: } void end_scope(){ - size_t pop_count = m_vars.size() - m_scopes.back(); + const size_t pop_count = m_vars.size() - m_scopes.back(); m_output << " add rsp, " << pop_count * 8 << "\n"; m_stack_size -= pop_count; for (int i = 0; i < pop_count; i++) { @@ -176,9 +175,7 @@ private: } std::string create_label() { - std::stringstream ss; - ss << ".label" << m_label_count++; - return ss.str(); + return ".label" + std::to_string(m_label_count++); } void push(const std::string& reg) { diff --git a/src/main.cxx b/src/main.cxx index ad7ffa0..cd6a2da 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -11,6 +11,7 @@ #include "tokenization.hxx" int main(int argc, char* argv[]) { + size_t memsize = 1024 * 1024 * 4; std::string outfile = "out.asm"; std::optional infile; int opt; @@ -57,6 +58,10 @@ int main(int argc, char* argv[]) { { std::stringstream contents_stream; std::fstream input(infile.value(), std::ios::in); + input.seekg(0, std::ios::end); + std::streampos fileSize = input.tellg(); + input.seekg(0, std::ios::beg); + memsize = fileSize * 64; contents_stream << input.rdbuf(); contents = contents_stream.str(); } @@ -64,7 +69,7 @@ int main(int argc, char* argv[]) { Tokenizer tokenizer(std::move(contents)); std::vector tokens = tokenizer.tokenize(); - Parser parser(std::move(tokens)); + Parser parser(std::move(tokens), std::move(memsize)); std::optional prog = parser.parse_prog(); if (!prog.has_value()) { @@ -72,9 +77,8 @@ int main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - Generator generator(prog.value()); - { + Generator generator(prog.value()); std::fstream output(outfile, std::ios::out); output << generator.gen_prog(); } diff --git a/src/parser.hxx b/src/parser.hxx index 2c30e34..e0133b1 100644 --- a/src/parser.hxx +++ b/src/parser.hxx @@ -85,9 +85,9 @@ namespace node { class Parser { public: - inline explicit Parser(std::vector tokens) + inline explicit Parser(std::vector tokens, size_t memsize) : m_tokens(std::move(tokens)), - m_allocator(1024 * 1024 * 4) { // 4 MB should be ok..? + m_allocator(std::move(memsize)) { // 4 MB should be ok..? // Erm! } @@ -142,8 +142,8 @@ public: break; // breaking bad 2 } - Token op = consume(); - int next_min_prec = prec.value() + 1; + const Token op = consume(); + const int next_min_prec = prec.value() + 1; auto expr_rhs = parse_expr(next_min_prec); if (!expr_rhs.has_value()) { err::expression({}); diff --git a/src/tokenization.hxx b/src/tokenization.hxx index 4d81ae5..a622a11 100644 --- a/src/tokenization.hxx +++ b/src/tokenization.hxx @@ -31,7 +31,7 @@ enum class TokenType { if_, }; -std::optional bin_prec(TokenType type) { +inline std::optional bin_prec(const TokenType type) { switch (type) { case TokenType::star: case TokenType::fslash: