#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().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(op)); case IR::OpType::FN: return GenerateFunction(reinterpret_cast(op)); case IR::OpType::CALL: return GenerateCall(reinterpret_cast(op)); // TODO: default: output().AppendFormat(" ; %d not implemented\n", op->GetType()); } } };