reshit my shit
This commit is contained in:
parent
ce81cb7f28
commit
0f201aa8c8
@ -1,29 +1,64 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <optional>
|
#include <cstddef>
|
||||||
#include <iostream>
|
#include <memory>
|
||||||
#include <stdlib.h>
|
#include <utility>
|
||||||
|
|
||||||
class ArenaAllocator {
|
class ArenaAllocator {
|
||||||
public:
|
public:
|
||||||
inline explicit ArenaAllocator(size_t bytes) : m_size(bytes) {
|
explicit ArenaAllocator(const size_t max_num_bytes)
|
||||||
m_buffer = static_cast<std::byte*>(malloc(m_size));
|
: m_size { max_num_bytes }
|
||||||
m_offset = m_buffer;
|
, m_buffer { new std::byte[max_num_bytes] }
|
||||||
|
, m_offset { m_buffer }
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
ArenaAllocator(const ArenaAllocator&) = delete;
|
||||||
inline T* alloc() {
|
ArenaAllocator& operator=(const ArenaAllocator&) = delete;
|
||||||
void* offset = m_offset;
|
|
||||||
m_offset += sizeof(T);
|
ArenaAllocator(ArenaAllocator&& other) noexcept
|
||||||
return static_cast<T*>(offset);
|
: 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 <typename T>
|
||||||
|
[[nodiscard]] T* alloc()
|
||||||
|
{
|
||||||
|
size_t remaining_num_bytes = m_size - static_cast<size_t>(m_offset - m_buffer);
|
||||||
|
auto pointer = static_cast<void*>(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<std::byte*>(aligned_address) + sizeof(T);
|
||||||
|
return static_cast<T*>(aligned_address);
|
||||||
|
}
|
||||||
|
|
||||||
inline ~ArenaAllocator() {
|
template <typename T, typename... Args>
|
||||||
free(m_buffer);
|
[[nodiscard]] T* emplace(Args&&... args)
|
||||||
|
{
|
||||||
|
const auto allocated_memory = alloc<T>();
|
||||||
|
return new (allocated_memory) T { std::forward<Args>(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:
|
private:
|
||||||
|
|||||||
@ -22,128 +22,127 @@ public:
|
|||||||
|
|
||||||
void gen_stmt(const node::Stmt* stmt) {
|
void gen_stmt(const node::Stmt* stmt) {
|
||||||
struct StmtVisitor { // Visiting the homies
|
struct StmtVisitor { // Visiting the homies
|
||||||
Generator* gen;
|
Generator& gen;
|
||||||
void operator()(const node::StmtExit* stmt_exit) const {
|
void operator()(const node::StmtExit* stmt_exit) const {
|
||||||
gen->gen_expr(stmt_exit->expr);
|
gen.gen_expr(stmt_exit->expr);
|
||||||
gen->m_output << " mov rax, 60\n";
|
gen.m_output << " mov rax, 60\n";
|
||||||
gen->pop("rdi");
|
gen.pop("rdi");
|
||||||
gen->m_output << " syscall\n";
|
gen.m_output << " syscall\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::StmtVar* stmt_var) {
|
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 (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()) {
|
||||||
if (it != gen->m_vars.cend()) {
|
|
||||||
err::redefine(stmt_var->ident.value.value());
|
err::redefine(stmt_var->ident.value.value());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
gen->m_vars.push_back({.name = stmt_var->ident.value.value(), .stack_loc = gen->m_stack_size});
|
gen.m_vars.push_back({.name = stmt_var->ident.value.value(), .stack_loc = gen.m_stack_size});
|
||||||
gen->gen_expr(stmt_var->expr);
|
gen.gen_expr(stmt_var->expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::StmtIf* stmt_if) const {
|
void operator()(const node::StmtIf* stmt_if) const {
|
||||||
gen->gen_expr(stmt_if->expr);
|
gen.gen_expr(stmt_if->expr);
|
||||||
gen->pop("rax");
|
gen.pop("rax");
|
||||||
std::string label = gen->create_label();
|
const std::string label = gen.create_label();
|
||||||
gen->m_output << " test rax, rax\n";
|
gen.m_output << " test rax, rax\n";
|
||||||
gen->m_output << " jz " << label << "\n";
|
gen.m_output << " jz " << label << "\n";
|
||||||
gen->gen_scope(stmt_if->scope);
|
gen.gen_scope(stmt_if->scope);
|
||||||
gen->m_output << "\n" << label << ":\n";
|
gen.m_output << "\n" << label << ":\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::Scope* scope) {
|
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);
|
std::visit(visitor, stmt->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_term(const node::Term* term) {
|
void gen_term(const node::Term* term) {
|
||||||
struct TermVisitor {
|
struct TermVisitor {
|
||||||
Generator* gen;
|
Generator& gen;
|
||||||
|
|
||||||
void operator()(const node::TermIntLit* term_int_lit) const {
|
void operator()(const node::TermIntLit* term_int_lit) const {
|
||||||
gen->m_output << " mov rax, " << term_int_lit->int_lit.value.value() << "\n";
|
gen.m_output << " mov rax, " << term_int_lit->int_lit.value.value() << "\n";
|
||||||
gen->push("rax");
|
gen.push("rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::TermIdent* term_ident) const {
|
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();});
|
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()) {
|
if (it == gen.m_vars.cend()) {
|
||||||
err::undeclared(term_ident->ident.value.value());
|
err::undeclared(term_ident->ident.value.value());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
std::stringstream offset;
|
std::stringstream offset;
|
||||||
offset << "QWORD [rsp + " << (gen->m_stack_size - (*it).stack_loc - 1) * 8 << "]";
|
offset << "QWORD [rsp + " << (gen.m_stack_size - it->stack_loc - 1) * 8 << "]";
|
||||||
gen->push(offset.str());
|
gen.push(offset.str());
|
||||||
}
|
}
|
||||||
void operator()(const node::TermParen* term_paren) const {
|
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);
|
std::visit(visitor, term->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_bin_expr(const node::BinExpr* bin_expr) {
|
void gen_bin_expr(const node::BinExpr* bin_expr) {
|
||||||
struct BinExprVisitor {
|
struct BinExprVisitor {
|
||||||
Generator* gen;
|
Generator& gen;
|
||||||
void operator()(const node::BinExprAdd* add) {
|
void operator()(const node::BinExprAdd* add) {
|
||||||
gen->gen_expr(add->rhs);
|
gen.gen_expr(add->rhs);
|
||||||
gen->gen_expr(add->lhs);
|
gen.gen_expr(add->lhs);
|
||||||
gen->pop("rax");
|
gen.pop("rax");
|
||||||
gen->pop("rbx");
|
gen.pop("rbx");
|
||||||
gen->m_output << " add rax, rbx\n";
|
gen.m_output << " add rax, rbx\n";
|
||||||
gen->push("rax");
|
gen.push("rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::BinExprMul* mul) {
|
void operator()(const node::BinExprMul* mul) {
|
||||||
gen->gen_expr(mul->rhs);
|
gen.gen_expr(mul->rhs);
|
||||||
gen->gen_expr(mul->lhs);
|
gen.gen_expr(mul->lhs);
|
||||||
gen->pop("rax");
|
gen.pop("rax");
|
||||||
gen->pop("rbx");
|
gen.pop("rbx");
|
||||||
gen->m_output << " mul rbx\n";
|
gen.m_output << " mul rbx\n";
|
||||||
gen->push("rax");
|
gen.push("rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::BinExprSub* sub) {
|
void operator()(const node::BinExprSub* sub) {
|
||||||
gen->gen_expr(sub->rhs);
|
gen.gen_expr(sub->rhs);
|
||||||
gen->gen_expr(sub->lhs);
|
gen.gen_expr(sub->lhs);
|
||||||
gen->pop("rax");
|
gen.pop("rax");
|
||||||
gen->pop("rbx");
|
gen.pop("rbx");
|
||||||
gen->m_output << " sub rax, rbx\n";
|
gen.m_output << " sub rax, rbx\n";
|
||||||
gen->push("rax");
|
gen.push("rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::BinExprDiv* div) {
|
void operator()(const node::BinExprDiv* div) {
|
||||||
gen->gen_expr(div->rhs);
|
gen.gen_expr(div->rhs);
|
||||||
gen->gen_expr(div->lhs);
|
gen.gen_expr(div->lhs);
|
||||||
gen->pop("rax");
|
gen.pop("rax");
|
||||||
gen->pop("rbx");
|
gen.pop("rbx");
|
||||||
gen->m_output << " div rbx\n";
|
gen.m_output << " div rbx\n";
|
||||||
gen->push("rax");
|
gen.push("rax");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BinExprVisitor visitor {.gen = this};
|
BinExprVisitor visitor {.gen = *this};
|
||||||
std::visit(visitor, bin_expr->var);
|
std::visit(visitor, bin_expr->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_expr(const node::Expr* expr) {
|
void gen_expr(const node::Expr* expr) {
|
||||||
struct ExprVisitor {
|
struct ExprVisitor {
|
||||||
Generator* gen;
|
Generator& gen;
|
||||||
|
|
||||||
void operator()(const node::Term* term) const {
|
void operator()(const node::Term* term) const {
|
||||||
gen->gen_term(term);
|
gen.gen_term(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const node::BinExpr* bin_expr) const {
|
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);
|
std::visit(visitor, expr->var);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +165,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void end_scope(){
|
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_output << " add rsp, " << pop_count * 8 << "\n";
|
||||||
m_stack_size -= pop_count;
|
m_stack_size -= pop_count;
|
||||||
for (int i = 0; i < pop_count; i++) {
|
for (int i = 0; i < pop_count; i++) {
|
||||||
@ -176,9 +175,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string create_label() {
|
std::string create_label() {
|
||||||
std::stringstream ss;
|
return ".label" + std::to_string(m_label_count++);
|
||||||
ss << ".label" << m_label_count++;
|
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(const std::string& reg) {
|
void push(const std::string& reg) {
|
||||||
|
|||||||
10
src/main.cxx
10
src/main.cxx
@ -11,6 +11,7 @@
|
|||||||
#include "tokenization.hxx"
|
#include "tokenization.hxx"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
size_t memsize = 1024 * 1024 * 4;
|
||||||
std::string outfile = "out.asm";
|
std::string outfile = "out.asm";
|
||||||
std::optional<std::string> infile;
|
std::optional<std::string> infile;
|
||||||
int opt;
|
int opt;
|
||||||
@ -57,6 +58,10 @@ int main(int argc, char* argv[]) {
|
|||||||
{
|
{
|
||||||
std::stringstream contents_stream;
|
std::stringstream contents_stream;
|
||||||
std::fstream input(infile.value(), std::ios::in);
|
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_stream << input.rdbuf();
|
||||||
contents = contents_stream.str();
|
contents = contents_stream.str();
|
||||||
}
|
}
|
||||||
@ -64,7 +69,7 @@ int main(int argc, char* argv[]) {
|
|||||||
Tokenizer tokenizer(std::move(contents));
|
Tokenizer tokenizer(std::move(contents));
|
||||||
std::vector<Token> tokens = tokenizer.tokenize();
|
std::vector<Token> tokens = tokenizer.tokenize();
|
||||||
|
|
||||||
Parser parser(std::move(tokens));
|
Parser parser(std::move(tokens), std::move(memsize));
|
||||||
std::optional<node::Prog> prog = parser.parse_prog();
|
std::optional<node::Prog> prog = parser.parse_prog();
|
||||||
|
|
||||||
if (!prog.has_value()) {
|
if (!prog.has_value()) {
|
||||||
@ -72,9 +77,8 @@ int main(int argc, char* argv[]) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Generator generator(prog.value());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Generator generator(prog.value());
|
||||||
std::fstream output(outfile, std::ios::out);
|
std::fstream output(outfile, std::ios::out);
|
||||||
output << generator.gen_prog();
|
output << generator.gen_prog();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,9 +85,9 @@ namespace node {
|
|||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
inline explicit Parser(std::vector<Token> tokens)
|
inline explicit Parser(std::vector<Token> tokens, size_t memsize)
|
||||||
: m_tokens(std::move(tokens)),
|
: 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!
|
// Erm!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +142,8 @@ public:
|
|||||||
break; // breaking bad 2
|
break; // breaking bad 2
|
||||||
}
|
}
|
||||||
|
|
||||||
Token op = consume();
|
const Token op = consume();
|
||||||
int next_min_prec = prec.value() + 1;
|
const int next_min_prec = prec.value() + 1;
|
||||||
auto expr_rhs = parse_expr(next_min_prec);
|
auto expr_rhs = parse_expr(next_min_prec);
|
||||||
if (!expr_rhs.has_value()) {
|
if (!expr_rhs.has_value()) {
|
||||||
err::expression({});
|
err::expression({});
|
||||||
|
|||||||
@ -31,7 +31,7 @@ enum class TokenType {
|
|||||||
if_,
|
if_,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<int> bin_prec(TokenType type) {
|
inline std::optional<int> bin_prec(const TokenType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TokenType::star:
|
case TokenType::star:
|
||||||
case TokenType::fslash:
|
case TokenType::fslash:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user