// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_CODEGEN_MACHINEINSTR_H #define RCC_CODEGEN_MACHINEINSTR_H #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/MachineOperand.h" #include "rcc/CodeGen/StableID.h" #include "rcc/Support/Error.h" #include #include #include #include #include #include #include #include #include namespace rcc { class MachineBasicBlock; class MachineFunction; class MachineMemOperand; class MachineRegisterInfo; class MachineInstr final { public: MachineInstr(const MachineInstr &) = delete; MachineInstr &operator=(const MachineInstr &) = delete; MachineInstr(MachineInstr &&) = delete; MachineInstr &operator=(MachineInstr &&) = delete; ~MachineInstr(); [[nodiscard]] Opcode opcode() const noexcept { return InstructionOpcode; } [[nodiscard]] Expected setOpcode(Opcode NewOpcode); [[nodiscard]] MachineInstrStableID stableID() const noexcept { return StableID; } [[nodiscard]] MachineFunction &function() noexcept { return *OwnerFunction; } [[nodiscard]] const MachineFunction &function() const noexcept { return *OwnerFunction; } [[nodiscard]] MachineBasicBlock *parent() noexcept { return ParentBlock; } [[nodiscard]] const MachineBasicBlock *parent() const noexcept { return ParentBlock; } [[nodiscard]] MachineInstr *previous() noexcept { return PreviousInstruction; } [[nodiscard]] const MachineInstr *previous() const noexcept { return PreviousInstruction; } [[nodiscard]] MachineInstr *next() noexcept { return NextInstruction; } [[nodiscard]] const MachineInstr *next() const noexcept { return NextInstruction; } [[nodiscard]] bool isLinked() const noexcept { return ParentBlock != nullptr; } [[nodiscard]] std::size_t operandCount() const noexcept { return Operands.size(); } [[nodiscard]] MachineOperand *operandAt(std::size_t Index) noexcept; [[nodiscard]] const MachineOperand *operandAt(std::size_t Index) const noexcept; [[nodiscard]] std::span operands() const noexcept { return Operands; } void reserveOperands(std::size_t Capacity); [[nodiscard]] Expected addOperand(MachineOperand &&Operand); [[nodiscard]] Expected insertOperand(std::size_t Index, MachineOperand &&Operand); [[nodiscard]] Expected eraseOperand(std::size_t Index); [[nodiscard]] Expected tieOperands(std::size_t DefIndex, std::size_t UseIndex); [[nodiscard]] Expected untieOperand(std::size_t Index); [[nodiscard]] Expected addMemOperand(const MachineMemOperand &MemOperand); [[nodiscard]] Expected eraseMemOperand(std::size_t Index); [[nodiscard]] std::span memOperands() const noexcept { return MemOperands; } [[nodiscard]] MachineInstrFlags flags() const noexcept { return Flags; } void setFlags(MachineInstrFlags NewFlags) noexcept { Flags = NewFlags; } [[nodiscard]] const std::optional &sourceLocation() const noexcept { return Location; } void setSourceLocation(SourceLocation NewLocation) { Location = std::move(NewLocation); } void clearSourceLocation() noexcept { Location.reset(); } [[nodiscard]] const std::optional &debugLocation() const noexcept { return DebugLocation; } [[nodiscard]] Expected setDebugLocation(MachineDebugLocation NewLocation); void clearDebugLocation() noexcept { DebugLocation.reset(); } [[nodiscard]] std::optional origin() const noexcept { return Origin; } void setOrigin(OriginID NewOrigin) noexcept { Origin = NewOrigin; } void clearOrigin() noexcept { Origin.reset(); } [[nodiscard]] std::uint32_t debugInstrNumber() const noexcept { return DebugInstrNumber; } [[nodiscard]] Expected setDebugInstrNumber(std::uint64_t Number); [[nodiscard]] Expected assignDebugInstrNumber(); void clearDebugInstrNumber() noexcept { DebugInstrNumber = 0; } [[nodiscard]] std::optional preInstrSymbol() const noexcept; [[nodiscard]] Expected setPreInstrSymbol(std::string Symbol); void clearPreInstrSymbol() noexcept { PreInstrSymbol.reset(); } [[nodiscard]] std::optional postInstrSymbol() const noexcept; [[nodiscard]] Expected setPostInstrSymbol(std::string Symbol); void clearPostInstrSymbol() noexcept { PostInstrSymbol.reset(); } [[nodiscard]] const std::optional &heapAllocMarker() const noexcept { return HeapAllocMarker; } [[nodiscard]] Expected setHeapAllocMarker(MachineMetadataReference Marker); void clearHeapAllocMarker() noexcept { HeapAllocMarker.reset(); } [[nodiscard]] const std::optional &pcSections() const noexcept { return PCSections; } [[nodiscard]] Expected setPCSections(MachineMetadataReference Sections); void clearPCSections() noexcept { PCSections.reset(); } [[nodiscard]] const std::optional &mmra() const noexcept { return MMRA; } [[nodiscard]] Expected setMMRA(MachineMetadataReference Metadata); void clearMMRA() noexcept { MMRA.reset(); } [[nodiscard]] std::optional cfiType() const noexcept { return CFIType; } [[nodiscard]] Expected setCFIType(std::uint64_t Type); void clearCFIType() noexcept { CFIType.reset(); } [[nodiscard]] std::optional deactivationSymbol() const noexcept; [[nodiscard]] Expected setDeactivationSymbol(std::string Symbol); void clearDeactivationSymbol() noexcept { DeactivationSymbol.reset(); } private: MachineInstr(MachineFunction &OwnerFunction, Opcode InstructionOpcode, MachineInstrStableID StableID); [[nodiscard]] MachineRegisterInfo *linkedRegisterInfo() noexcept; [[nodiscard]] Expected attachToBlock(MachineBasicBlock &Block); void detachFromBlock() noexcept; void adjustTiesForInsertion(std::size_t Index) noexcept; void adjustTiesForErasure(std::size_t Index) noexcept; MachineFunction *OwnerFunction; Opcode InstructionOpcode; MachineInstrStableID StableID; MachineBasicBlock *ParentBlock = nullptr; MachineInstr *PreviousInstruction = nullptr; MachineInstr *NextInstruction = nullptr; std::vector Operands; std::vector MemOperands; MachineInstrFlags Flags; std::optional Location; std::optional DebugLocation; std::optional Origin; std::uint32_t DebugInstrNumber = 0; std::optional PreInstrSymbol; std::optional PostInstrSymbol; std::optional HeapAllocMarker; std::optional PCSections; std::optional MMRA; std::optional CFIType; std::optional DeactivationSymbol; friend class MachineArena; friend class MachineBasicBlock; friend class MachineFunction; }; } // namespace rcc #endif // RCC_CODEGEN_MACHINEINSTR_H