// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_CODEGEN_MACHINEIRBUILDER_H #define RCC_CODEGEN_MACHINEIRBUILDER_H #include "rcc/CodeGen/GenericOpcodes.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 #include #include namespace rcc { class MachineBasicBlock; class MachineFunction; class MachineInstr; class MachineMemOperand; class MachineRegisterInfo; class RegisterMask; class GISelCSEInfo; 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 addIntegerImmediate(APInt Value, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addFloatingImmediate(APFloat 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 addLiveOutRegisterMask(std::shared_ptr Mask, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addMetadata(MachineMetadataValue Value, 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 addCFIInstruction(CFIInstructionIndex Index, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addIntrinsic(IntrinsicID ID, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addIntegerPredicate(IntegerPredicate Predicate, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addFloatingPredicate(FloatingPredicate Predicate, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addShuffleMask(std::vector Elements, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addDebugInstrRef(std::uint64_t InstructionNumber, std::uint64_t OperandNumber, std::uint32_t TargetFlags = 0); [[nodiscard]] Expected addLaneMask(LaneMask Mask, 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 setDebugLocation(MachineDebugLocation NewLocation); [[nodiscard]] Expected clearDebugLocation(); [[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 validateCFIReference(CFIInstructionIndex 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 DebugLocation; std::optional Origin; bool IsBuilt = false; friend class MachineIRBuilder; }; class MachineIRBuilderResult final { public: enum class Kind : std::uint8_t { Register, Type, }; MachineIRBuilderResult(Register Reg) noexcept : Reg(Reg), ResultKind(Kind::Register) {} MachineIRBuilderResult(LowLevelType Type) noexcept : Type(Type), ResultKind(Kind::Type) {} [[nodiscard]] Kind kind() const noexcept { return ResultKind; } [[nodiscard]] Register reg() const noexcept; [[nodiscard]] LowLevelType type() const noexcept; [[nodiscard]] Expected type(const MachineRegisterInfo &MRI) const; [[nodiscard]] Expected addDef(MachineRegisterInfo &MRI, MachineInstrBuilder &Builder) const; private: Register Reg; LowLevelType Type; Kind ResultKind; }; class MachineIRBuilder { 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; virtual ~MachineIRBuilder() = default; [[nodiscard]] MachineFunction &function() noexcept { return *Function; } [[nodiscard]] MachineFunction &function() const noexcept { return *Function; } [[nodiscard]] const TargetDescription &target() const noexcept { return *Target; } [[nodiscard]] MachineBasicBlock *insertionBlock() const noexcept { return InsertBlock; } [[nodiscard]] MachineInstr *insertionInstruction() const noexcept { return InsertBefore; } [[nodiscard]] GISelCSEInfo *getCSEInfo() noexcept { return CSEInfo; } [[nodiscard]] GISelCSEInfo *getCSEInfo() const noexcept { return CSEInfo; } void setCSEInfo(GISelCSEInfo *Info) noexcept { CSEInfo = Info; } [[nodiscard]] Expected verifyInsertPoint() const; [[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; [[nodiscard]] Expected buildInstr(Opcode InstructionOpcode, std::initializer_list Destinations, std::initializer_list Sources) const; [[nodiscard]] virtual Expected buildInstr(Opcode InstructionOpcode, std::span Destinations, std::span Sources) const; [[nodiscard]] Expected buildTrunc(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildCopy(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildImplicitDef(MachineIRBuilderResult Destination) const; [[nodiscard]] Expected buildAnyExt(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildZExt(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildSExt(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] GenericOpcode getBoolExtOp(bool IsVector, bool IsFloatingPoint) const noexcept; [[nodiscard]] Expected buildUndef(MachineIRBuilderResult Destination) const; [[nodiscard]] Expected buildAnyExtOrTrunc(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildZExtOrTrunc(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildSExtOrTrunc(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] virtual Expected buildConstant(MachineIRBuilderResult Destination, APInt Value) const; [[nodiscard]] Expected buildConstant(MachineIRBuilderResult Destination, std::int64_t Value) const; [[nodiscard]] virtual Expected buildSExtInReg(MachineIRBuilderResult Destination, Register Source, std::uint32_t Width) const; [[nodiscard]] Expected buildAnd(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildOr(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildXor(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildAdd(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildSub(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildShl(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildLShr(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildAShr(MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildPtrToInt(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildIntToPtr(MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildICmp(IntegerPredicate Predicate, MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildMergeLikeInstr(MachineIRBuilderResult Destination, const std::vector &Sources) const; [[nodiscard]] Expected buildMergeValues(MachineIRBuilderResult Destination, const std::vector &Sources) const; [[nodiscard]] Expected buildUnmergeValues(const std::vector &Destinations, Register Source) const; [[nodiscard]] virtual Expected buildExtract(MachineIRBuilderResult Destination, Register Source, std::uint64_t Offset) const; [[nodiscard]] Expected buildInsert(MachineIRBuilderResult Destination, Register Source, Register Inserted, std::uint64_t Offset) const; private: [[nodiscard]] Expected buildUnary(Opcode InstructionOpcode, MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected buildBinary(Opcode InstructionOpcode, MachineIRBuilderResult Destination, Register Left, Register Right) const; [[nodiscard]] Expected buildExtOrTrunc(Opcode ExtensionOpcode, MachineIRBuilderResult Destination, Register Source) const; [[nodiscard]] Expected registerType(Register Reg) const; [[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; GISelCSEInfo *CSEInfo = nullptr; }; } // namespace rcc #endif // RCC_CODEGEN_MACHINEIRBUILDER_H