From 8553df97bbc6154dae9d0ad861857e71a0efa420 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 1 Aug 2026 13:09:30 +0800 Subject: [CodeGen] Add transactional MachineIR builder Validate insertion cursors, operand ownership, descriptor constraints, ties, implicit registers, and memory operands before allocating or publishing an instruction. Share instruction legality checks with the verifier path and preserve deterministic insertion order. --- .../include/rcc/CodeGen/InstructionDescriptor.h | 26 ++++ backend/include/rcc/CodeGen/MachineIRBuilder.h | 161 +++++++++++++++++++++ backend/include/rcc/CodeGen/MachineInstr.h | 4 +- 3 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 backend/include/rcc/CodeGen/MachineIRBuilder.h (limited to 'backend/include/rcc') diff --git a/backend/include/rcc/CodeGen/InstructionDescriptor.h b/backend/include/rcc/CodeGen/InstructionDescriptor.h index c6049b9..94ea374 100644 --- a/backend/include/rcc/CodeGen/InstructionDescriptor.h +++ b/backend/include/rcc/CodeGen/InstructionDescriptor.h @@ -23,6 +23,7 @@ namespace rcc { class MachineInstr; +class MachineMemOperand; class MachineRegisterInfo; class OperandKindSet final { @@ -217,6 +218,13 @@ struct ImmediatePredicate final { std::function Predicate; }; +struct MachineOperandTie final { + std::size_t DefOperand; + std::size_t UseOperand; + + friend bool operator==(MachineOperandTie Left, MachineOperandTie Right) noexcept = default; +}; + class InstructionSet final { public: [[nodiscard]] static Expected @@ -232,6 +240,15 @@ public: [[nodiscard]] Expected validateExplicitOperands(Opcode InstructionOpcode, std::span Operands, const MachineRegisterInfo &RegInfo) const; + [[nodiscard]] Expected validateOperandTies(Opcode InstructionOpcode, + std::span ExplicitOperands, + std::span Ties) const; + [[nodiscard]] Expected + validateImplicitOperands(Opcode InstructionOpcode, + std::span ImplicitOperands) const; + [[nodiscard]] Expected + validateMemOperands(Opcode InstructionOpcode, + std::span MemOperands) const; [[nodiscard]] Expected validateInstruction(const MachineInstr &Instruction, const MachineRegisterInfo &RegInfo) const; @@ -248,6 +265,15 @@ private: [[nodiscard]] Expected validateExplicitOperands(const InstructionDescriptor &Descriptor, std::span Operands, const MachineRegisterInfo &RegInfo) const; + [[nodiscard]] Expected validateOperandTies(const InstructionDescriptor &Descriptor, + std::span ExplicitOperands, + std::span Ties) const; + [[nodiscard]] Expected + validateImplicitOperands(const InstructionDescriptor &Descriptor, + std::span ImplicitOperands) const; + [[nodiscard]] Expected + validateMemOperands(const InstructionDescriptor &Descriptor, + std::span MemOperands) const; [[nodiscard]] Expected validateOperand(const OperandDescriptor &Descriptor, const MachineOperand &Operand, const MachineRegisterInfo &RegInfo) const; diff --git a/backend/include/rcc/CodeGen/MachineIRBuilder.h b/backend/include/rcc/CodeGen/MachineIRBuilder.h new file mode 100644 index 0000000..02e47ff --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineIRBuilder.h @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEIRBUILDER_H +#define RCC_CODEGEN_MACHINEIRBUILDER_H + +#include "rcc/CodeGen/InstructionDescriptor.h" +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/MachineOperand.h" +#include "rcc/CodeGen/Register.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class MachineBasicBlock; +class MachineFunction; +class MachineInstr; +class MachineMemOperand; +class RegisterMask; + +class MachineInstrBuilder final { +public: + MachineInstrBuilder(const MachineInstrBuilder &) = delete; + MachineInstrBuilder &operator=(const MachineInstrBuilder &) = delete; + MachineInstrBuilder(MachineInstrBuilder &&Other) noexcept; + MachineInstrBuilder &operator=(MachineInstrBuilder &&Other) noexcept; + ~MachineInstrBuilder() = default; + + [[nodiscard]] Expected addOperand(MachineOperand &&Operand); + [[nodiscard]] Expected addImplicitOperand(MachineOperand &&Operand); + + [[nodiscard]] Expected addDef(Register Reg, RegisterOperandFlags AdditionalFlags = {}, + SubRegIndex SubReg = {}, std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addUse(Register Reg, RegisterOperandFlags AdditionalFlags = {}, + SubRegIndex SubReg = {}, std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addDefUse(Register Reg, RegisterOperandFlags AdditionalFlags = {}, + SubRegIndex SubReg = {}, std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addImplicitDef(Register Reg, + RegisterOperandFlags AdditionalFlags = {}, + SubRegIndex SubReg = {}, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addImplicitUse(Register Reg, + RegisterOperandFlags AdditionalFlags = {}, + SubRegIndex SubReg = {}, + std::uint32_t TargetFlags = 0); + + [[nodiscard]] Expected addImmediate(std::int64_t Value, std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addFloatingImmediate(FloatingPointBits Bits, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addBasicBlock(MachineBasicBlock &Block, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addFrameIndex(FrameIndex Index, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addConstantPool(ConstantPoolIndex Index, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addJumpTable(JumpTableIndex Index, std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addGlobalSymbol(std::string Name, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addExternalSymbol(std::string Name, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addBlockAddress(std::string FunctionName, std::string BlockName, + std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addRegisterMask(std::shared_ptr Mask, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addMetadata(std::string Marker, std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addTargetIndex(TargetIndex Index, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + [[nodiscard]] Expected addMCSymbol(std::string Name, std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0); + + [[nodiscard]] Expected tieOperands(std::size_t DefOperand, std::size_t UseOperand); + [[nodiscard]] Expected addMemOperand(const MachineMemOperand &MemOperand); + + [[nodiscard]] Expected setFlags(MachineInstrFlags NewFlags); + + [[nodiscard]] Expected setSourceLocation(SourceLocation NewLocation); + [[nodiscard]] Expected clearSourceLocation(); + + [[nodiscard]] Expected setOrigin(OriginID NewOrigin); + [[nodiscard]] Expected clearOrigin(); + + [[nodiscard]] Expected build(); + +private: + MachineInstrBuilder(MachineFunction &Function, const InstructionSet &Instructions, + const InstructionDescriptor &Descriptor, MachineBasicBlock &InsertBlock, + MachineInstr *InsertBefore) noexcept; + + [[nodiscard]] Expected ensurePending() const; + [[nodiscard]] Expected validateInsertionPoint() const; + [[nodiscard]] Expected validateOperandOwnership(const MachineOperand &Operand) const; + [[nodiscard]] std::vector collectOperandTies() const; + [[nodiscard]] Expected appendRegister(Register Reg, RegisterOperandFlags Flags, + SubRegIndex SubReg, std::uint32_t TargetFlags, + bool IsImplicit); + + MachineFunction *Function; + const InstructionSet *Instructions; + const InstructionDescriptor *Descriptor; + MachineBasicBlock *InsertBlock; + MachineInstr *InsertBefore; + std::vector ExplicitOperands; + std::vector ExtraImplicitOperands; + std::vector RequestedTies; + std::vector MemOperands; + MachineInstrFlags Flags; + std::optional Location; + std::optional Origin; + bool IsBuilt = false; + + friend class MachineIRBuilder; +}; + +class MachineIRBuilder final { +public: + MachineIRBuilder(MachineFunction &Function, const InstructionSet &Instructions) noexcept + : Function(&Function), Instructions(&Instructions) {} + MachineIRBuilder(const MachineIRBuilder &) = delete; + MachineIRBuilder &operator=(const MachineIRBuilder &) = delete; + MachineIRBuilder(MachineIRBuilder &&) = delete; + MachineIRBuilder &operator=(MachineIRBuilder &&) = delete; + + [[nodiscard]] MachineFunction &function() noexcept { + return *Function; + } + + [[nodiscard]] const MachineFunction &function() const noexcept { + return *Function; + } + + [[nodiscard]] Expected setInsertPoint(MachineBasicBlock &Block); + [[nodiscard]] Expected setInsertPointBefore(MachineInstr &Instruction); + [[nodiscard]] Expected setInsertPointAfter(MachineInstr &Instruction); + void clearInsertPoint() noexcept { + InsertBlock = nullptr; + InsertBefore = nullptr; + } + + [[nodiscard]] Expected buildInstr(Opcode InstructionOpcode) const; + +private: + [[nodiscard]] Expected validateBlock(const MachineBasicBlock &Block) const; + [[nodiscard]] Expected validateInstruction(const MachineInstr &Instruction) const; + + MachineFunction *Function; + const InstructionSet *Instructions; + MachineBasicBlock *InsertBlock = nullptr; + MachineInstr *InsertBefore = nullptr; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEIRBUILDER_H diff --git a/backend/include/rcc/CodeGen/MachineInstr.h b/backend/include/rcc/CodeGen/MachineInstr.h index 376273f..bcae306 100644 --- a/backend/include/rcc/CodeGen/MachineInstr.h +++ b/backend/include/rcc/CodeGen/MachineInstr.h @@ -87,8 +87,8 @@ public: } void reserveOperands(std::size_t Capacity); - [[nodiscard]] Expected addOperand(MachineOperand Operand); - [[nodiscard]] Expected insertOperand(std::size_t Index, MachineOperand Operand); + [[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); -- cgit v1.2.3