// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_MC_MCASSEMBLER_H #define RCC_MC_MCASSEMBLER_H #include "rcc/MC/MCAsmBackend.h" #include "rcc/MC/MCCodeEmitter.h" #include "rcc/MC/MCDwarfFrameEmitter.h" #include "rcc/MC/MCObjectWriter.h" #include "rcc/MC/MCStreamer.h" #include "rcc/Support/Error.h" #include #include #include #include #include #include #include #include namespace rcc::mc { class MCAssembler final { public: MCAssembler(const MCCodeEmitter &Emitter, const MCAsmBackend &Backend) noexcept : Emitter(&Emitter), Backend(&Backend) {} [[nodiscard]] Expected switchSection(MCSectionRef Section); [[nodiscard]] Expected emitLabel(MCSymbolRef Symbol); [[nodiscard]] Expected emitInstruction(const MCInst &Instruction); [[nodiscard]] Expected emitValue(MCExprRef Value, std::uint8_t Size); [[nodiscard]] Expected emitBytes(std::span Bytes); [[nodiscard]] Expected emitZeroFill(std::uint64_t Size); [[nodiscard]] Expected emitAlignment(std::uint64_t Alignment, std::uint8_t Fill, std::uint64_t MaximumBytes); [[nodiscard]] Expected emitSymbolAttribute(MCSymbolRef Symbol, MCSymbolAttribute Attribute); [[nodiscard]] Expected emitSymbolSize(MCSymbolRef Symbol, MCExprRef Size); [[nodiscard]] Expected emitCommonSymbol(MCSymbolRef Symbol, std::uint64_t Size, std::uint64_t Alignment); [[nodiscard]] Expected emitCFI(const MCCFIInstruction &Instruction); [[nodiscard]] Expected configureDwarfFrame(MCSectionRef Section, MCDwarfFrameInfo Info); [[nodiscard]] Expected assemble(); private: struct InstructionFragment final { MCInst Instruction; }; struct DataFragment final { std::vector Bytes; std::vector Fixups; }; struct AlignmentFragment final { std::uint64_t Alignment = 1; std::uint8_t Fill = 0; std::uint64_t MaximumBytes = 0; }; struct ZeroFillFragment final { std::uint64_t Size = 0; }; using FragmentPayload = std::variant; struct Fragment final { FragmentPayload Payload; std::uint64_t Offset = 0; std::uint64_t Size = 0; std::vector EncodedBytes; std::vector Fixups; }; struct SectionData final { MCSectionRef Section; std::vector Fragments; std::uint64_t AddressSize = 0; std::uint64_t Alignment = 1; }; struct SymbolData final { MCSymbolRef Symbol; MCObjectSymbolBinding Binding = MCObjectSymbolBinding::Local; bool BindingWasSet = false; MCObjectSymbolType Type = MCObjectSymbolType::None; MCObjectSymbolVisibility Visibility = MCObjectSymbolVisibility::Default; std::optional SectionIndex; std::size_t FragmentIndex = 0; MCExprRef Size; std::uint64_t CommonSize = 0; std::uint64_t CommonAlignment = 0; }; struct CFIEvent final { MCCFIInstruction Instruction; std::size_t FragmentIndex = 0; }; struct CFIProcedure final { MCSymbolRef Function; std::size_t SectionIndex = 0; std::size_t BeginFragmentIndex = 0; std::size_t EndFragmentIndex = 0; std::vector Events; bool IsClosed = false; }; [[nodiscard]] Expected currentSectionIndex() const; [[nodiscard]] SymbolData &getOrCreateSymbol(MCSymbolRef Symbol); [[nodiscard]] Expected encodeFragments(); [[nodiscard]] Expected layoutAndRelax(); [[nodiscard]] Expected finalizeObject(); [[nodiscard]] Expected appendDwarfFrame(MCAssembledObject &Object) const; [[nodiscard]] std::optional symbolOffset(const SymbolData &Symbol) const; const MCCodeEmitter *Emitter; const MCAsmBackend *Backend; std::vector Sections; std::unordered_map SectionIndices; std::vector Symbols; std::unordered_map SymbolIndices; std::optional CurrentSection; std::vector CFIProcedures; std::optional ActiveCFIProcedure; MCSectionRef EHFrameSection; std::optional DwarfFrameInfo; bool WasAssembled = false; }; } // namespace rcc::mc #endif // RCC_MC_MCASSEMBLER_H