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. --- backend/include/rcc/CodeGen/MachineIRBuilder.h | 161 +++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 backend/include/rcc/CodeGen/MachineIRBuilder.h (limited to 'backend/include/rcc/CodeGen/MachineIRBuilder.h') 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 -- cgit v1.2.3