Files
pl/include/codegen/targets/fasm_x86_64_linux.hpp
2026-01-04 20:19:24 +01:00

71 lines
1.9 KiB
C++

#pragma once
#include "codegen/codegen.hpp"
#include "ir/op.hpp"
#include "ir/ops.hpp"
#include "prelude/linkedlist.hpp"
class FasmX86_64Generator : public CodeGenerator
{
public:
FasmX86_64Generator() = default;
public:
bool Generate(const IR::OpView* ops) override
{
output().Extend("format ELF64\n");
output().Extend("section '.text' executable\n");
for (size_t i = 0; i < ops->size; ++i)
{
GenerateStatement(ops->data[i]);
}
return true;
}
private:
void GenerateExtern(IR::ExternOp* extrn)
{
// TODO: instead of __<symbol, use some random UID or hash string
// for safety and collision considerations
output().AppendFormat("extrn '%s' as __%s\n", extrn->symbol().c_str(), extrn->symbol().c_str());
output().AppendFormat("%s = PLT __%s\n", extrn->symbol().c_str(), extrn->symbol().c_str());
}
void GenerateFunction(IR::FnOp* fn)
{
output().AppendFormat("public %s\n", fn->name().c_str());
output().AppendFormat("%s:\n", fn->name().c_str());
output().Extend(" push rbp\n");
output().Extend(" mov rbp, rsp\n");
for (auto cur = fn->body().ops().Begin(); cur != nullptr; cur = cur->next)
{
GenerateStatement(cur->value);
}
output().Extend(" leave\n");
output().Extend(" ret\n");
}
void GenerateCall(IR::CallOp* call)
{
output().AppendFormat(" call %s\n", call->callee().c_str());
}
void GenerateStatement(IR::Op* op)
{
switch(op->GetType())
{
case IR::OpType::EXTERN:
return GenerateExtern(reinterpret_cast<IR::ExternOp*>(op));
case IR::OpType::FN:
return GenerateFunction(reinterpret_cast<IR::FnOp*>(op));
case IR::OpType::CALL:
return GenerateCall(reinterpret_cast<IR::CallOp*>(op));
// TODO:
default: output().AppendFormat(" ; %d not implemented\n", op->GetType());
}
}
};