// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_MC_MCSTREAMER_H #define RCC_MC_MCSTREAMER_H #include "rcc/MC/MCCFI.h" #include "rcc/MC/MCInst.h" #include "rcc/MC/MCInstPrinter.h" #include "rcc/MC/MCSection.h" #include "rcc/MC/MCSymbol.h" #include "rcc/Support/Error.h" #include #include #include #include #include namespace rcc::mc { enum class MCSymbolAttribute : std::uint8_t { Global, Weak, Local, Hidden, Protected, Function, Object, TLSObject, }; class MCStreamer { public: virtual ~MCStreamer() = default; [[nodiscard]] virtual Expected switchSection(MCSectionRef Section) = 0; [[nodiscard]] virtual Expected emitLabel(MCSymbolRef Symbol) = 0; [[nodiscard]] virtual Expected emitInstruction(const MCInst &Instruction) = 0; [[nodiscard]] virtual Expected emitValue(MCExprRef Value, std::uint8_t Size) = 0; [[nodiscard]] virtual Expected emitBytes(std::span Bytes) = 0; [[nodiscard]] virtual Expected emitZeroFill(std::uint64_t Size) = 0; [[nodiscard]] virtual Expected emitAlignment(std::uint64_t Alignment, std::uint8_t Fill = 0, std::uint64_t MaximumBytes = 0) = 0; [[nodiscard]] virtual Expected emitSymbolAttribute(MCSymbolRef Symbol, MCSymbolAttribute Attribute) = 0; [[nodiscard]] virtual Expected emitSymbolSize(MCSymbolRef Symbol, MCExprRef Size) = 0; [[nodiscard]] virtual Expected emitCommonSymbol(MCSymbolRef Symbol, std::uint64_t Size, std::uint64_t Alignment) = 0; [[nodiscard]] virtual Expected emitDirective(std::string_view Name, std::string_view Arguments = {}) = 0; [[nodiscard]] virtual Expected emitCFI(const MCCFIInstruction &Instruction) = 0; [[nodiscard]] virtual Expected emitInlineAssembly(std::string_view Text) = 0; [[nodiscard]] virtual Expected emitComment(std::string_view Text) = 0; [[nodiscard]] virtual Expected finish() = 0; }; class AsmTextStreamer final : public MCStreamer { public: explicit AsmTextStreamer(const MCInstPrinter &Printer) noexcept : Printer(&Printer) {} [[nodiscard]] Expected switchSection(MCSectionRef Section) override; [[nodiscard]] Expected emitLabel(MCSymbolRef Symbol) override; [[nodiscard]] Expected emitInstruction(const MCInst &Instruction) override; [[nodiscard]] Expected emitValue(MCExprRef Value, std::uint8_t Size) override; [[nodiscard]] Expected emitBytes(std::span Bytes) override; [[nodiscard]] Expected emitZeroFill(std::uint64_t Size) override; [[nodiscard]] Expected emitAlignment(std::uint64_t Alignment, std::uint8_t Fill = 0, std::uint64_t MaximumBytes = 0) override; [[nodiscard]] Expected emitSymbolAttribute(MCSymbolRef Symbol, MCSymbolAttribute Attribute) override; [[nodiscard]] Expected emitSymbolSize(MCSymbolRef Symbol, MCExprRef Size) override; [[nodiscard]] Expected emitCommonSymbol(MCSymbolRef Symbol, std::uint64_t Size, std::uint64_t Alignment) override; [[nodiscard]] Expected emitDirective(std::string_view Name, std::string_view Arguments = {}) override; [[nodiscard]] Expected emitCFI(const MCCFIInstruction &Instruction) override; [[nodiscard]] Expected emitInlineAssembly(std::string_view Text) override; [[nodiscard]] Expected emitComment(std::string_view Text) override; [[nodiscard]] Expected finish() override; [[nodiscard]] Expected takeOutput(); private: [[nodiscard]] Expected appendLine(std::string_view Prefix, std::string_view Text); [[nodiscard]] Expected requireActiveSection() const; const MCInstPrinter *Printer; MCSectionRef CurrentSection; std::unordered_set DefinedSymbols; std::string Output; bool IsFinished = false; bool OutputWasTaken = false; }; } // namespace rcc::mc #endif // RCC_MC_MCSTREAMER_H