From c759cebef15bdac2ef160065efd116fe6ed540a7 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 1 Aug 2026 05:27:13 +0800 Subject: [CodeGen] Build the core MachineIR object model Add arena-owned, address-stable MachineFunction, MachineBasicBlock, and MachineInstr nodes with intrusive layout and instruction lists. Model every required MachineOperand category, reciprocal ties, source state, and immutable per-instruction memory references. Implement physical and virtual register def-use chains whose back-links survive operand vector moves, plus vreg properties, tombstones, live-ins, reserved registers, and atomic CFG updates. Exercise ownership, reallocation, unlink/relink, cross-function rejection, and sanitizer paths. --- backend/include/rcc/CodeGen/MachineBasicBlock.h | 151 ++++++++++ backend/include/rcc/CodeGen/MachineCFGUpdater.h | 39 +++ backend/include/rcc/CodeGen/MachineFunction.h | 130 ++++++++ backend/include/rcc/CodeGen/MachineInstr.h | 164 +++++++++++ backend/include/rcc/CodeGen/MachineMemOperand.h | 6 + backend/include/rcc/CodeGen/MachineOperand.h | 344 ++++++++++++++++++++++ backend/include/rcc/CodeGen/MachineRegisterInfo.h | 168 +++++++++++ 7 files changed, 1002 insertions(+) create mode 100644 backend/include/rcc/CodeGen/MachineBasicBlock.h create mode 100644 backend/include/rcc/CodeGen/MachineCFGUpdater.h create mode 100644 backend/include/rcc/CodeGen/MachineFunction.h create mode 100644 backend/include/rcc/CodeGen/MachineInstr.h create mode 100644 backend/include/rcc/CodeGen/MachineOperand.h create mode 100644 backend/include/rcc/CodeGen/MachineRegisterInfo.h (limited to 'backend/include/rcc') diff --git a/backend/include/rcc/CodeGen/MachineBasicBlock.h b/backend/include/rcc/CodeGen/MachineBasicBlock.h new file mode 100644 index 0000000..ba59160 --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineBasicBlock.h @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEBASICBLOCK_H +#define RCC_CODEGEN_MACHINEBASICBLOCK_H + +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/Register.h" +#include "rcc/CodeGen/StableID.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include + +namespace rcc { + +class MachineBasicBlock; +class MachineCFGUpdater; +class MachineFunction; +class MachineInstr; + +struct MachineSuccessor final { + MachineBasicBlock *Block = nullptr; + BranchProbability Probability; + + friend bool operator==(const MachineSuccessor &Left, const MachineSuccessor &Right) = default; +}; + +struct MachineBasicBlockLiveIn final { + PhysicalRegister PhysReg; + LaneMask Lanes = LaneMask::all(); + + friend bool operator==(const MachineBasicBlockLiveIn &Left, + const MachineBasicBlockLiveIn &Right) = default; +}; + +class MachineBasicBlock final { +public: + MachineBasicBlock(const MachineBasicBlock &) = delete; + MachineBasicBlock &operator=(const MachineBasicBlock &) = delete; + MachineBasicBlock(MachineBasicBlock &&) = delete; + MachineBasicBlock &operator=(MachineBasicBlock &&) = delete; + ~MachineBasicBlock() = default; + + [[nodiscard]] MachineBlockStableID stableID() const noexcept { + return StableID; + } + + [[nodiscard]] MachineFunction &function() noexcept { + return *OwnerFunction; + } + + [[nodiscard]] const MachineFunction &function() const noexcept { + return *OwnerFunction; + } + + [[nodiscard]] bool isLinked() const noexcept { + return IsLinked; + } + + [[nodiscard]] MachineBasicBlock *previous() noexcept { + return PreviousBlock; + } + + [[nodiscard]] const MachineBasicBlock *previous() const noexcept { + return PreviousBlock; + } + + [[nodiscard]] MachineBasicBlock *next() noexcept { + return NextBlock; + } + + [[nodiscard]] const MachineBasicBlock *next() const noexcept { + return NextBlock; + } + + [[nodiscard]] MachineInstr *firstInstruction() noexcept { + return FirstInstruction; + } + + [[nodiscard]] const MachineInstr *firstInstruction() const noexcept { + return FirstInstruction; + } + + [[nodiscard]] MachineInstr *lastInstruction() noexcept { + return LastInstruction; + } + + [[nodiscard]] const MachineInstr *lastInstruction() const noexcept { + return LastInstruction; + } + + [[nodiscard]] std::size_t instructionCount() const noexcept; + [[nodiscard]] Expected appendInstruction(MachineInstr &Instruction); + [[nodiscard]] Expected insertInstructionBefore(MachineInstr &Position, + MachineInstr &Instruction); + [[nodiscard]] Expected insertInstructionAfter(MachineInstr &Position, + MachineInstr &Instruction); + [[nodiscard]] Expected removeInstruction(MachineInstr &Instruction); + void clearInstructions() noexcept; + + [[nodiscard]] std::span predecessors() const noexcept { + return Predecessors; + } + + [[nodiscard]] std::span successors() const noexcept { + return Successors; + } + + [[nodiscard]] Expected addLiveIn(PhysicalRegister PhysReg, + LaneMask Lanes = LaneMask::all()); + [[nodiscard]] Expected removeLiveIn(PhysicalRegister PhysReg); + [[nodiscard]] std::span liveIns() const noexcept { + return LiveIns; + } + + [[nodiscard]] std::optional denseNumber() const noexcept { + return DenseNumber; + } + + [[nodiscard]] std::optional layoutIndex() const noexcept { + return LayoutIndex; + } + +private: + MachineBasicBlock(MachineFunction &OwnerFunction, MachineBlockStableID StableID) + : OwnerFunction(&OwnerFunction), StableID(StableID) {} + + MachineFunction *OwnerFunction; + MachineBlockStableID StableID; + bool IsLinked = false; + MachineBasicBlock *PreviousBlock = nullptr; + MachineBasicBlock *NextBlock = nullptr; + MachineInstr *FirstInstruction = nullptr; + MachineInstr *LastInstruction = nullptr; + std::vector Predecessors; + std::vector Successors; + std::vector LiveIns; + std::optional DenseNumber; + std::optional LayoutIndex; + + friend class MachineArena; + friend class MachineCFGUpdater; + friend class MachineFunction; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEBASICBLOCK_H diff --git a/backend/include/rcc/CodeGen/MachineCFGUpdater.h b/backend/include/rcc/CodeGen/MachineCFGUpdater.h new file mode 100644 index 0000000..4359538 --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineCFGUpdater.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINECFGUPDATER_H +#define RCC_CODEGEN_MACHINECFGUPDATER_H + +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/Support/Error.h" + +namespace rcc { + +class MachineBasicBlock; +class MachineFunction; + +class MachineCFGUpdater final { +public: + explicit MachineCFGUpdater(MachineFunction &Function) noexcept : Function(&Function) {} + + [[nodiscard]] Expected + addSuccessor(MachineBasicBlock &From, MachineBasicBlock &To, + BranchProbability Probability = BranchProbability::zero()); + [[nodiscard]] Expected removeSuccessor(MachineBasicBlock &From, MachineBasicBlock &To); + [[nodiscard]] Expected replaceSuccessor(MachineBasicBlock &From, + MachineBasicBlock &OldTarget, + MachineBasicBlock &NewTarget); + [[nodiscard]] Expected updateBranchProbability(MachineBasicBlock &From, + MachineBasicBlock &To, + BranchProbability Probability); + [[nodiscard]] Expected transferSuccessors(MachineBasicBlock &From, MachineBasicBlock &To); + [[nodiscard]] Expected disconnectBlock(MachineBasicBlock &Block); + +private: + [[nodiscard]] Expected verifyOwnership(const MachineBasicBlock &Block) const; + + MachineFunction *Function; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINECFGUPDATER_H diff --git a/backend/include/rcc/CodeGen/MachineFunction.h b/backend/include/rcc/CodeGen/MachineFunction.h new file mode 100644 index 0000000..487fb5b --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineFunction.h @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEFUNCTION_H +#define RCC_CODEGEN_MACHINEFUNCTION_H + +#include "rcc/CodeGen/MachineFunctionProperties.h" +#include "rcc/CodeGen/MachineRegisterInfo.h" +#include "rcc/CodeGen/StableID.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class MachineArena; +class MachineBasicBlock; +class MachineCFGUpdater; +class MachineInstr; +class MachineMemOperand; +struct MachineMemOperandDesc; +class Opcode; + +class MachineFunction final { +public: + [[nodiscard]] static Expected> + create(std::string Name, MachineFunctionStableID StableID); + + MachineFunction(const MachineFunction &) = delete; + MachineFunction &operator=(const MachineFunction &) = delete; + MachineFunction(MachineFunction &&) = delete; + MachineFunction &operator=(MachineFunction &&) = delete; + ~MachineFunction(); + + [[nodiscard]] std::string_view name() const noexcept { + return Name; + } + + [[nodiscard]] MachineFunctionStableID stableID() const noexcept { + return StableID; + } + + [[nodiscard]] MachineRegisterInfo ®isterInfo() noexcept { + return RegInfo; + } + + [[nodiscard]] const MachineRegisterInfo ®isterInfo() const noexcept { + return RegInfo; + } + + [[nodiscard]] MachineFunctionProperties &properties() noexcept { + return Properties; + } + + [[nodiscard]] const MachineFunctionProperties &properties() const noexcept { + return Properties; + } + + [[nodiscard]] Expected createBasicBlock(); + [[nodiscard]] Expected createInstruction(Opcode InstructionOpcode); + [[nodiscard]] Expected + createMemOperand(MachineMemOperandDesc Description); + + [[nodiscard]] Expected appendBlock(MachineBasicBlock &Block); + [[nodiscard]] Expected insertBlockBefore(MachineBasicBlock &Position, + MachineBasicBlock &Block); + [[nodiscard]] Expected removeBlock(MachineBasicBlock &Block); + + [[nodiscard]] MachineBasicBlock *firstBlock() noexcept { + return FirstBlock; + } + + [[nodiscard]] const MachineBasicBlock *firstBlock() const noexcept { + return FirstBlock; + } + + [[nodiscard]] MachineBasicBlock *lastBlock() noexcept { + return LastBlock; + } + + [[nodiscard]] const MachineBasicBlock *lastBlock() const noexcept { + return LastBlock; + } + + [[nodiscard]] std::size_t blockCount() const noexcept; + [[nodiscard]] std::span allBlocks() const noexcept { + return AllBlocks; + } + + [[nodiscard]] std::span allInstructions() const noexcept { + return AllInstructions; + } + + [[nodiscard]] std::span allMemOperands() const noexcept { + return AllMemOperands; + } + + [[nodiscard]] bool ownsMemOperand(const MachineMemOperand &MemOperand) const noexcept; + + [[nodiscard]] MachineCFGUpdater cfgUpdater() noexcept; + void renumberBlocks() noexcept; + +private: + MachineFunction(std::string Name, MachineFunctionStableID StableID); + + std::string Name; + MachineFunctionStableID StableID; + MachineRegisterInfo RegInfo; + MachineFunctionProperties Properties; + MachineBasicBlock *FirstBlock = nullptr; + MachineBasicBlock *LastBlock = nullptr; + std::vector AllBlocks; + std::vector AllInstructions; + std::vector AllMemOperands; + StableIDGenerator BlockIDGenerator; + StableIDGenerator InstrIDGenerator; + std::unique_ptr Arena; + + friend class MachineBasicBlock; + friend class MachineCFGUpdater; + friend class MachineInstr; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEFUNCTION_H diff --git a/backend/include/rcc/CodeGen/MachineInstr.h b/backend/include/rcc/CodeGen/MachineInstr.h new file mode 100644 index 0000000..376273f --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineInstr.h @@ -0,0 +1,164 @@ +// 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 + +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]] std::optional origin() const noexcept { + return Origin; + } + + void setOrigin(OriginID NewOrigin) noexcept { + Origin = NewOrigin; + } + + void clearOrigin() noexcept { + Origin.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 Origin; + + friend class MachineArena; + friend class MachineBasicBlock; + friend class MachineFunction; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEINSTR_H diff --git a/backend/include/rcc/CodeGen/MachineMemOperand.h b/backend/include/rcc/CodeGen/MachineMemOperand.h index 52514f9..e513385 100644 --- a/backend/include/rcc/CodeGen/MachineMemOperand.h +++ b/backend/include/rcc/CodeGen/MachineMemOperand.h @@ -207,6 +207,12 @@ struct MachineMemOperandDesc final { class MachineMemOperand final { public: + MachineMemOperand(const MachineMemOperand &) = default; + MachineMemOperand &operator=(const MachineMemOperand &) = default; + MachineMemOperand(MachineMemOperand &&) noexcept = default; + MachineMemOperand &operator=(MachineMemOperand &&) noexcept = default; + ~MachineMemOperand() = default; + [[nodiscard]] static Expected create(MachineMemOperandDesc Description); [[nodiscard]] const MachineMemOperandDesc &description() const noexcept { diff --git a/backend/include/rcc/CodeGen/MachineOperand.h b/backend/include/rcc/CodeGen/MachineOperand.h new file mode 100644 index 0000000..0da9f25 --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineOperand.h @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEOPERAND_H +#define RCC_CODEGEN_MACHINEOPERAND_H + +#include "rcc/CodeGen/LowLevelType.h" +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/Register.h" +#include "rcc/CodeGen/RegisterMask.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class MachineBasicBlock; +class MachineInstr; +class MachineRegisterInfo; +class RegOperandIterator; + +class FloatingPointBits final { +public: + [[nodiscard]] static Expected create(FloatSemantics Semantics, + std::span Words); + + [[nodiscard]] FloatSemantics semantics() const noexcept { + return Semantics; + } + + [[nodiscard]] std::uint32_t bitWidth() const noexcept { + return getFloatSemanticsBitWidth(Semantics).value_or(0); + } + + [[nodiscard]] std::span words() const noexcept { + return std::span(Words).first(WordCount); + } + + friend bool operator==(const FloatingPointBits &Left, const FloatingPointBits &Right) = default; + +private: + FloatingPointBits(FloatSemantics Semantics, std::array Words, + std::uint8_t WordCount) noexcept + : Semantics(Semantics), Words(Words), WordCount(WordCount) {} + + FloatSemantics Semantics; + std::array Words; + std::uint8_t WordCount; +}; + +enum class RegisterOperandFlag : std::uint8_t { + Define, + Use, + Implicit, + Kill, + Dead, + Undef, + EarlyClobber, + InternalRead, + Renamable, + Debug, + Count, +}; + +class RegisterOperandFlags final { +public: + constexpr RegisterOperandFlags() noexcept = default; + + RegisterOperandFlags(std::initializer_list Flags) noexcept; + + [[nodiscard]] constexpr bool has(RegisterOperandFlag Flag) const noexcept { + const auto Index = static_cast(Flag); + if (Index >= static_cast(RegisterOperandFlag::Count)) + return false; + return (Mask & (std::uint16_t{1} << Index)) != 0; + } + + constexpr void set(RegisterOperandFlag Flag) noexcept { + const auto Index = static_cast(Flag); + if (Index < static_cast(RegisterOperandFlag::Count)) + Mask |= std::uint16_t{1} << Index; + } + + constexpr void clear(RegisterOperandFlag Flag) noexcept { + const auto Index = static_cast(Flag); + if (Index < static_cast(RegisterOperandFlag::Count)) + Mask &= static_cast(~(std::uint16_t{1} << Index)); + } + + [[nodiscard]] constexpr std::uint16_t rawValue() const noexcept { + return Mask; + } + + friend constexpr bool operator==(RegisterOperandFlags Left, + RegisterOperandFlags Right) noexcept = default; + +private: + std::uint16_t Mask = 0; +}; + +struct FloatingImmediateOperand final { + FloatingPointBits Bits; + + friend bool operator==(const FloatingImmediateOperand &Left, + const FloatingImmediateOperand &Right) = default; +}; + +struct BasicBlockOperand final { + MachineBasicBlock *Block = nullptr; + + friend bool operator==(BasicBlockOperand Left, BasicBlockOperand Right) noexcept = default; +}; + +struct FrameIndexOperand final { + FrameIndex Index; + std::int64_t Offset = 0; + + friend constexpr bool operator==(FrameIndexOperand Left, + FrameIndexOperand Right) noexcept = default; +}; + +struct ConstantPoolOperand final { + ConstantPoolIndex Index; + std::int64_t Offset = 0; + + friend constexpr bool operator==(ConstantPoolOperand Left, + ConstantPoolOperand Right) noexcept = default; +}; + +struct JumpTableOperand final { + JumpTableIndex Index; + + friend constexpr bool operator==(JumpTableOperand Left, + JumpTableOperand Right) noexcept = default; +}; + +struct GlobalSymbolOperand final { + std::string Name; + std::int64_t Offset = 0; + + friend bool operator==(const GlobalSymbolOperand &Left, + const GlobalSymbolOperand &Right) = default; +}; + +struct ExternalSymbolOperand final { + std::string Name; + std::int64_t Offset = 0; + + friend bool operator==(const ExternalSymbolOperand &Left, + const ExternalSymbolOperand &Right) = default; +}; + +struct BlockAddressOperand final { + std::string FunctionName; + std::string BlockName; + std::int64_t Offset = 0; + + friend bool operator==(const BlockAddressOperand &Left, + const BlockAddressOperand &Right) = default; +}; + +struct RegisterMaskOperand final { + std::shared_ptr Mask; + + friend bool operator==(const RegisterMaskOperand &Left, + const RegisterMaskOperand &Right) = default; +}; + +struct MetadataOperand final { + std::string Marker; + + friend bool operator==(const MetadataOperand &Left, const MetadataOperand &Right) = default; +}; + +struct TargetIndexOperand final { + TargetIndex Index; + std::int64_t Offset = 0; + + friend constexpr bool operator==(TargetIndexOperand Left, + TargetIndexOperand Right) noexcept = default; +}; + +struct MCSymbolOperand final { + std::string Name; + std::int64_t Offset = 0; + + friend bool operator==(const MCSymbolOperand &Left, const MCSymbolOperand &Right) = default; +}; + +class MachineOperand final { +public: + enum class Kind : std::uint8_t { + Register, + Immediate, + FloatingImmediate, + BasicBlock, + FrameIndex, + ConstantPoolIndex, + JumpTableIndex, + GlobalSymbol, + ExternalSymbol, + BlockAddress, + RegisterMask, + Metadata, + TargetIndex, + MCSymbol, + }; + + MachineOperand(const MachineOperand &) = delete; + MachineOperand &operator=(const MachineOperand &) = delete; + MachineOperand(MachineOperand &&Other) noexcept; + MachineOperand &operator=(MachineOperand &&Other) noexcept; + ~MachineOperand(); + + [[nodiscard]] static Expected registerOperand(Register Reg, + RegisterOperandFlags Flags, + SubRegIndex SubReg = {}, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand immediate(std::int64_t Value, std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand floatingImmediate(FloatingPointBits Bits, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand basicBlock(MachineBasicBlock &Block, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand frameIndex(FrameIndex Index, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand constantPool(ConstantPoolIndex Index, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand jumpTable(JumpTableIndex Index, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static Expected + globalSymbol(std::string Name, std::int64_t Offset = 0, std::uint32_t TargetFlags = 0); + [[nodiscard]] static Expected + externalSymbol(std::string Name, std::int64_t Offset = 0, std::uint32_t TargetFlags = 0); + [[nodiscard]] static Expected blockAddress(std::string FunctionName, + std::string BlockName, + std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static Expected + registerMask(std::shared_ptr Mask, std::uint32_t TargetFlags = 0); + [[nodiscard]] static Expected metadata(std::string Marker, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static MachineOperand targetIndex(TargetIndex Index, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] static Expected mcSymbol(std::string Name, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + + [[nodiscard]] Kind kind() const noexcept { + return OperandKind; + } + + [[nodiscard]] bool isRegister() const noexcept { + return OperandKind == Kind::Register; + } + + [[nodiscard]] std::optional registerValue() const noexcept; + [[nodiscard]] RegisterOperandFlags registerFlags() const noexcept { + return RegFlags; + } + [[nodiscard]] SubRegIndex subReg() const noexcept { + return RegSubReg; + } + [[nodiscard]] bool isDef() const noexcept; + [[nodiscard]] bool isUse() const noexcept; + [[nodiscard]] bool isDebugUse() const noexcept; + [[nodiscard]] bool isImplicit() const noexcept; + + [[nodiscard]] Expected setRegister(Register Reg); + [[nodiscard]] Expected setRegisterFlags(RegisterOperandFlags Flags); + [[nodiscard]] Expected setSubReg(SubRegIndex SubReg); + + [[nodiscard]] std::optional tiedOperandIndex() const noexcept { + return TiedOperandIndex; + } + + [[nodiscard]] std::uint32_t targetFlags() const noexcept { + return TargetFlags; + } + + void setTargetFlags(std::uint32_t NewTargetFlags) noexcept { + TargetFlags = NewTargetFlags; + } + + [[nodiscard]] MachineInstr *parent() noexcept { + return Parent; + } + + [[nodiscard]] const MachineInstr *parent() const noexcept { + return Parent; + } + + template [[nodiscard]] const PayloadT *getIf() const noexcept { + return std::get_if(&Storage); + } + + [[nodiscard]] MachineOperand cloneDetached() const; + +private: + using OperandStorage = + std::variant; + + MachineOperand(Kind OperandKind, OperandStorage Storage, std::uint32_t TargetFlags = 0) + : OperandKind(OperandKind), Storage(std::move(Storage)), TargetFlags(TargetFlags) {} + + [[nodiscard]] static Expected verifyRegisterFlags(RegisterOperandFlags Flags); + void attachTo(MachineInstr &Instruction, MachineRegisterInfo *RegInfo); + void detachFromInstruction() noexcept; + void linkToRegInfo(MachineRegisterInfo &RegInfo); + void unlinkFromRegInfo() noexcept; + void takeRegLinkFrom(MachineOperand &Other) noexcept; + void setTiedOperandIndex(std::optional Index) noexcept { + TiedOperandIndex = Index; + } + + Kind OperandKind; + OperandStorage Storage; + RegisterOperandFlags RegFlags; + SubRegIndex RegSubReg; + std::optional TiedOperandIndex; + std::uint32_t TargetFlags = 0; + MachineInstr *Parent = nullptr; + MachineRegisterInfo *LinkedRegInfo = nullptr; + MachineOperand **PreviousRegLink = nullptr; + MachineOperand *NextRegOperand = nullptr; + + friend class MachineInstr; + friend class MachineRegisterInfo; + friend class RegOperandIterator; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEOPERAND_H diff --git a/backend/include/rcc/CodeGen/MachineRegisterInfo.h b/backend/include/rcc/CodeGen/MachineRegisterInfo.h new file mode 100644 index 0000000..495853a --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineRegisterInfo.h @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEREGISTERINFO_H +#define RCC_CODEGEN_MACHINEREGISTERINFO_H + +#include "rcc/CodeGen/LowLevelType.h" +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/Register.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class MachineOperand; + +class RegOperandIterator final { +public: + using difference_type = std::ptrdiff_t; // NOLINT(readability-identifier-naming) + using value_type = MachineOperand; // NOLINT(readability-identifier-naming) + using pointer = MachineOperand *; // NOLINT(readability-identifier-naming) + using reference = MachineOperand &; // NOLINT(readability-identifier-naming) + using iterator_category = // NOLINT(readability-identifier-naming) + std::forward_iterator_tag; + + RegOperandIterator() = default; + + [[nodiscard]] reference operator*() const noexcept; + [[nodiscard]] pointer operator->() const noexcept; + RegOperandIterator &operator++() noexcept; + RegOperandIterator operator++(int) noexcept; + + friend bool operator==(const RegOperandIterator &Left, const RegOperandIterator &Right) noexcept { + return Left.Current == Right.Current; + } + +private: + RegOperandIterator(MachineOperand *Current, bool RequireUse, bool RequireDef, + bool SkipDebug) noexcept; + + void skipFiltered() noexcept; + + MachineOperand *Current = nullptr; + bool RequireUse = false; + bool RequireDef = false; + bool SkipDebug = false; + + friend class RegOperandRange; + friend class MachineRegisterInfo; +}; + +class RegOperandRange final { +public: + [[nodiscard]] RegOperandIterator begin() const noexcept { + return RegOperandIterator(Head, RequireUse, RequireDef, SkipDebug); + } + + [[nodiscard]] RegOperandIterator end() const noexcept { + return {}; + } + +private: + RegOperandRange(MachineOperand *Head, bool RequireUse, bool RequireDef, bool SkipDebug) noexcept + : Head(Head), RequireUse(RequireUse), RequireDef(RequireDef), SkipDebug(SkipDebug) {} + + MachineOperand *Head = nullptr; + bool RequireUse = false; + bool RequireDef = false; + bool SkipDebug = false; + + friend class MachineRegisterInfo; +}; + +struct VirtualRegisterInfo final { + std::optional Type; + std::optional Bank; + std::optional RegClass; + std::vector AllocationHints; + bool IsTombstone = false; +}; + +struct PhysicalRegisterLiveIn final { + PhysicalRegister PhysReg; + std::optional InitialVirtualRegister; + + friend bool operator==(const PhysicalRegisterLiveIn &Left, + const PhysicalRegisterLiveIn &Right) = default; +}; + +class MachineRegisterInfo final { +public: + MachineRegisterInfo() = default; + MachineRegisterInfo(const MachineRegisterInfo &) = delete; + MachineRegisterInfo &operator=(const MachineRegisterInfo &) = delete; + MachineRegisterInfo(MachineRegisterInfo &&) = delete; + MachineRegisterInfo &operator=(MachineRegisterInfo &&) = delete; + ~MachineRegisterInfo(); + + [[nodiscard]] Expected createVirtualRegister(); + [[nodiscard]] Expected createVirtualRegister(LLT Type); + [[nodiscard]] Expected eraseVirtualRegister(Register Reg); + + [[nodiscard]] bool isKnownVirtualRegister(Register Reg) const noexcept; + [[nodiscard]] Expected> + virtualRegisterInfo(Register Reg); + [[nodiscard]] Expected> + virtualRegisterInfo(Register Reg) const; + + [[nodiscard]] Expected setType(Register Reg, LLT Type); + [[nodiscard]] Expected clearType(Register Reg); + [[nodiscard]] Expected setRegisterBank(Register Reg, RegisterBankID Bank); + [[nodiscard]] Expected clearRegisterBank(Register Reg); + [[nodiscard]] Expected setRegisterClass(Register Reg, RegisterClassID RegClass); + [[nodiscard]] Expected clearRegisterClass(Register Reg); + [[nodiscard]] Expected addAllocationHint(Register Reg, PhysicalRegister Hint); + void clearAllVirtualRegisterTypes() noexcept; + + [[nodiscard]] Expected + addLiveIn(PhysicalRegister PhysReg, + std::optional InitialVirtualRegister = std::nullopt); + [[nodiscard]] std::span liveIns() const noexcept { + return LiveIns; + } + + [[nodiscard]] Expected reservePhysicalRegister(PhysicalRegister PhysReg); + [[nodiscard]] bool isReserved(PhysicalRegister PhysReg) const noexcept; + [[nodiscard]] std::span reservedRegisters() const noexcept { + return ReservedRegisters; + } + + [[nodiscard]] RegOperandRange regOperands(Register Reg) noexcept; + [[nodiscard]] RegOperandRange regNoDebugOperands(Register Reg) noexcept; + [[nodiscard]] RegOperandRange useOperands(Register Reg, bool IncludeDebug = true) noexcept; + [[nodiscard]] RegOperandRange defOperands(Register Reg) noexcept; + + [[nodiscard]] bool useEmpty(Register Reg, bool IncludeDebug = true) const noexcept; + [[nodiscard]] bool hasOneUse(Register Reg, bool IncludeDebug = true) const noexcept; + [[nodiscard]] const MachineOperand *getUniqueVRegDef(Register Reg) const noexcept; + [[nodiscard]] Expected replaceRegWith(Register OldReg, Register NewReg); + + [[nodiscard]] Expected verifyDefUseChains() const; + +private: + struct RegOperandListHead final { + MachineOperand *Head = nullptr; + }; + + [[nodiscard]] MachineOperand *headFor(Register Reg) const noexcept; + void linkOperand(MachineOperand &Operand); + + std::vector VirtualRegisters; + std::vector LiveIns; + std::vector ReservedRegisters; + std::unordered_map> DefUseHeads; + + friend class MachineOperand; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEREGISTERINFO_H -- cgit v1.2.3