feat: plan for register allocation + temp fix for 'E' not being printed

This commit is contained in:
2025-12-26 22:15:54 +01:00
parent 7f73b742c2
commit 3b8dfc4dae
3 changed files with 71 additions and 25 deletions

20
TODO.md Normal file
View File

@@ -0,0 +1,20 @@
0. Define how many physical regs are available, which are caller-saved and callee-saved
1. Implement if-else and while statements
2. Find out what use[B] and def[B] are for each block
3. Define successors and predecessors of each block and make them accessible
4. Compute liveIn[B] and liveOut[B] for each block
Classic equations:
liveIn[B] = use[B] (liveOut[B] - def[B])
liveOut[B] = liveIn[S] for S in succ[B]
5. Linear scan register allocation
- Instruction numbering + per-instruction liveness
- Live intervals
- Linear scan allocator with ~6 fake regs
- Spill to stack slots
- Add “CALL clobbers regs” rule

View File

@@ -8,6 +8,7 @@ class StackFasmX86_64Generator : public CodeGenerator
{ {
public: public:
~StackFasmX86_64Generator() override = default; ~StackFasmX86_64Generator() override = default;
private: private:
StringView GetTempAddr(IR::Value reg) StringView GetTempAddr(IR::Value reg)
{ {
@@ -21,19 +22,22 @@ private:
case IR::IRSlot::Type::REGISTRY: case IR::IRSlot::Type::REGISTRY:
{ {
StringBuilder sb; StringBuilder sb;
sb.AppendFormat("r%d", slot.GetSlot() + 10); // for r10, r11, r12 etc. sb.AppendFormat("r%d", slot.GetSlot() + 12); // for r10, r11, r12 etc.
return sb.view(); return sb.view();
} break; }
break;
case IR::IRSlot::Type::STACK: case IR::IRSlot::Type::STACK:
{ {
StringBuilder sb; StringBuilder sb;
sb.AppendFormat("[rbp-%d]", slot.GetSlot()); // for r10, r11, r12 etc. sb.AppendFormat("[rbp-%d]", slot.GetSlot()); // for r10, r11, r12 etc.
return sb.view(); return sb.view();
} break; }
break;
default: default:
assert(0 && "TODO: either unreachable or handle properly"); assert(0 && "TODO: either unreachable or handle properly");
} }
} }
private: private:
void GenerateOp(const IR::Op *op) void GenerateOp(const IR::Op *op)
{ {
@@ -135,7 +139,9 @@ private:
appendf("mov %s, rax\n", GetSlotAddr(result_slot).c_str()); appendf("mov %s, rax\n", GetSlotAddr(result_slot).c_str());
} }
break; break;
default: appendf("; NOT HANDLED\n; %s\n", op->Format(0).c_str()); break; default:
appendf("; NOT HANDLED\n; %s\n", op->Format(0).c_str());
break;
} }
} }
@@ -147,10 +153,13 @@ private:
m_output->VAppendFormat(fmt, args); m_output->VAppendFormat(fmt, args);
va_end(args); va_end(args);
} }
public: public:
StringView GetOutput() { return m_output->view(); } StringView GetOutput() { return m_output->view(); }
private: private:
StringBuilder *m_output = nullptr; StringBuilder *m_output = nullptr;
public: public:
void Generate(const char *filename, View<IR::Op *> ops) override void Generate(const char *filename, View<IR::Op *> ops) override
{ {
@@ -164,6 +173,7 @@ public:
GenerateOp(op); GenerateOp(op);
} }
} }
public: public:
// StackAllocator* m_stack = nullptr; // StackAllocator* m_stack = nullptr;
// TODO: handle sub-blocks // TODO: handle sub-blocks

View File

@@ -1,5 +1,7 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <cstdio>
#include <cstdlib>
#include <print> #include <print>
#include "parser/lexer.hpp" #include "parser/lexer.hpp"
#include "parser/ast.hpp" #include "parser/ast.hpp"
@@ -9,7 +11,8 @@
void dump_tokens(const char *filename, Lexer *lexer) void dump_tokens(const char *filename, Lexer *lexer)
{ {
while (lexer->NextToken()) { while (lexer->NextToken())
{
std::print("{}:{}:{}: ", filename, lexer->token().line_number, lexer->token().offset_start); std::print("{}:{}:{}: ", filename, lexer->token().line_number, lexer->token().offset_start);
if (lexer->token().token == TokenType::Id) if (lexer->token().token == TokenType::Id)
std::println("id = {}", lexer->token().string); std::println("id = {}", lexer->token().string);
@@ -23,15 +26,19 @@ void dump_tokens(const char* filename, Lexer* lexer)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char *filename; char *filename;
if (argc > 1) { if (argc > 1)
{
filename = (++argv)[0]; filename = (++argv)[0];
} else { }
else
{
fprintf(stderr, "ERROR: Input file is required.\n"); fprintf(stderr, "ERROR: Input file is required.\n");
return 1; return 1;
} }
std::ifstream f(filename); std::ifstream f(filename);
if (!f.is_open()) { if (!f.is_open())
{
fprintf(stderr, "ERROR: Failed to open input file: %s\n", filename); fprintf(stderr, "ERROR: Failed to open input file: %s\n", filename);
return 1; return 1;
} }
@@ -55,11 +62,20 @@ int main(int argc, char** argv)
printf("%s\n", ops.data[i]->Format(0).c_str()); printf("%s\n", ops.data[i]->Format(0).c_str());
} }
// StackFasmX86_64Generator gen; StackFasmX86_64Generator gen;
// gen.Generate(filename, ops); gen.Generate(filename, ops);
// printf("%s\n", gen.GetOutput().c_str()); StringView output = gen.GetOutput();
FILE *file = fopen("out.asm", "w");
fwrite(output.c_str(), output.size - 1, sizeof(char), file);
fclose(file);
system("fasm out.asm");
system("gcc -o out out.o");
return 0; return 0;
} }