// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_CODEGEN_MACHINEIRBUILDER_H #define RCC_CODEGEN_MACHINEIRBUILDER_H #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/MachineOperand.h" #include "rcc/CodeGen/Register.h" #include "rcc/CodeGen/TargetDescription.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 TargetDescription &Target, const InstructionDescriptor &Descriptor, MachineBasicBlock &InsertBlock, MachineInstr *InsertBefore) noexcept; [[nodiscard]] Expected ensurePending() const; [[nodiscard]] Expected validateInsertionPoint() const; [[nodiscard]] Expected validateFrameReference(FrameIndex Index) const; [[nodiscard]] Expected validateConstantPoolReference(ConstantPoolIndex Index) const; [[nodiscard]] Expected validateJumpTableReference(JumpTableIndex Index) 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 TargetDescription *Target; 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 TargetDescription &Target) noexcept : Function(&Function), Target(&Target) {} 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 TargetDescription *Target; MachineBasicBlock *InsertBlock = nullptr; MachineInstr *InsertBefore = nullptr; }; } // namespace rcc #endif // RCC_CODEGEN_MACHINEIRBUILDER_H