71 lines
1.9 KiB
C++
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());
|
|
}
|
|
}
|
|
};
|