//===- Instruction.h --------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_SANDBOXIR_INSTRUCTION_H #define LLVM_SANDBOXIR_INSTRUCTION_H #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/PatternMatch.h" #include "llvm/SandboxIR/BasicBlock.h" #include "llvm/SandboxIR/Constant.h" #include "llvm/SandboxIR/User.h" #include "llvm/Support/Compiler.h" namespace llvm::sandboxir { // Forward declaration for MSVC. class IntrinsicInst; class InsertPosition { BBIterator InsertAt; public: InsertPosition(BasicBlock *InsertAtEnd) { assert(InsertAtEnd != nullptr && "Expected non-null!"); InsertAt = InsertAtEnd->end(); } InsertPosition(BBIterator InsertAt) : InsertAt(InsertAt) {} operator BBIterator() { return InsertAt; } const BBIterator &getIterator() const { return InsertAt; } Instruction &operator*() { return *InsertAt; } BasicBlock *getBasicBlock() const { return InsertAt.getNodeParent(); } }; /// A sandboxir::User with operands, opcode and linked with previous/next /// instructions in an instruction list. class Instruction : public User { public: enum class Opcode { #define OP(OPC) OPC, #define OPCODES(...) __VA_ARGS__ #define DEF_INSTR(ID, OPC, CLASS) OPC #include "llvm/SandboxIR/Values.def" }; protected: Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I, sandboxir::Context &SBCtx) : User(ID, I, SBCtx), Opc(Opc) {} Opcode Opc; /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This /// returns its topmost LLVM IR instruction. LLVM_ABI llvm::Instruction *getTopmostLLVMInstruction() const; friend class VAArgInst; // For getTopmostLLVMInstruction(). friend class FreezeInst; // For getTopmostLLVMInstruction(). friend class FenceInst; // For getTopmostLLVMInstruction(). friend class SelectInst; // For getTopmostLLVMInstruction(). friend class ExtractElementInst; // For getTopmostLLVMInstruction(). friend class InsertElementInst; // For getTopmostLLVMInstruction(). friend class ShuffleVectorInst; // For getTopmostLLVMInstruction(). friend class ExtractValueInst; // For getTopmostLLVMInstruction(). friend class InsertValueInst; // For getTopmostLLVMInstruction(). friend class BranchInst; // For getTopmostLLVMInstruction(). friend class LoadInst; // For getTopmostLLVMInstruction(). friend class StoreInst; // For getTopmostLLVMInstruction(). friend class ReturnInst; // For getTopmostLLVMInstruction(). friend class CallInst; // For getTopmostLLVMInstruction(). friend class InvokeInst; // For getTopmostLLVMInstruction(). friend class CallBrInst; // For getTopmostLLVMInstruction(). friend class LandingPadInst; // For getTopmostLLVMInstruction(). friend class CatchPadInst; // For getTopmostLLVMInstruction(). friend class CleanupPadInst; // For getTopmostLLVMInstruction(). friend class CatchReturnInst; // For getTopmostLLVMInstruction(). friend class CleanupReturnInst; // For getTopmostLLVMInstruction(). friend class GetElementPtrInst; // For getTopmostLLVMInstruction(). friend class ResumeInst; // For getTopmostLLVMInstruction(). friend class CatchSwitchInst; // For getTopmostLLVMInstruction(). friend class SwitchInst; // For getTopmostLLVMInstruction(). friend class UnaryOperator; // For getTopmostLLVMInstruction(). friend class BinaryOperator; // For getTopmostLLVMInstruction(). friend class AtomicRMWInst; // For getTopmostLLVMInstruction(). friend class AtomicCmpXchgInst; // For getTopmostLLVMInstruction(). friend class AllocaInst; // For getTopmostLLVMInstruction(). friend class CastInst; // For getTopmostLLVMInstruction(). friend class PHINode; // For getTopmostLLVMInstruction(). friend class UnreachableInst; // For getTopmostLLVMInstruction(). friend class CmpInst; // For getTopmostLLVMInstruction(). /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program /// order. virtual SmallVector getLLVMInstrs() const = 0; friend class EraseFromParent; // For getLLVMInstrs(). /// Helper function for create(). It sets the builder's insert position /// according to \p Pos. static IRBuilder<> &setInsertPos(InsertPosition Pos) { auto *WhereBB = Pos.getBasicBlock(); auto WhereIt = Pos.getIterator(); auto &Ctx = WhereBB->getContext(); auto &Builder = Ctx.getLLVMIRBuilder(); if (WhereIt != WhereBB->end()) Builder.SetInsertPoint((*Pos).getTopmostLLVMInstruction()); else Builder.SetInsertPoint(cast(WhereBB->Val)); return Builder; } public: LLVM_ABI static const char *getOpcodeName(Opcode Opc); /// This is used by BasicBlock::iterator. virtual unsigned getNumOfIRInstrs() const = 0; /// \Returns a BasicBlock::iterator for this Instruction. LLVM_ABI BBIterator getIterator() const; /// \Returns the next sandboxir::Instruction in the block, or nullptr if at /// the end of the block. LLVM_ABI Instruction *getNextNode() const; /// \Returns the previous sandboxir::Instruction in the block, or nullptr if /// at the beginning of the block. LLVM_ABI Instruction *getPrevNode() const; /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode /// state to allow for new SandboxIR-specific instructions. Opcode getOpcode() const { return Opc; } const char *getOpcodeName() const { return getOpcodeName(Opc); } const DataLayout &getDataLayout() const { return cast(Val)->getModule()->getDataLayout(); } // Note that these functions below are calling into llvm::Instruction. // A sandbox IR instruction could introduce a new opcode that could change the // behavior of one of these functions. It is better that these functions are // only added as needed and new sandbox IR instructions must explicitly check // if any of these functions could have a different behavior. bool isTerminator() const { return cast(Val)->isTerminator(); } bool isUnaryOp() const { return cast(Val)->isUnaryOp(); } bool isBinaryOp() const { return cast(Val)->isBinaryOp(); } bool isIntDivRem() const { return cast(Val)->isIntDivRem(); } bool isShift() const { return cast(Val)->isShift(); } bool isCast() const { return cast(Val)->isCast(); } bool isFuncletPad() const { return cast(Val)->isFuncletPad(); } bool isSpecialTerminator() const { return cast(Val)->isSpecialTerminator(); } bool isOnlyUserOfAnyOperand() const { return cast(Val)->isOnlyUserOfAnyOperand(); } bool isLogicalShift() const { return cast(Val)->isLogicalShift(); } //===--------------------------------------------------------------------===// // Metadata manipulation. //===--------------------------------------------------------------------===// /// Return true if the instruction has any metadata attached to it. bool hasMetadata() const { return cast(Val)->hasMetadata(); } /// Return true if this instruction has metadata attached to it other than a /// debug location. bool hasMetadataOtherThanDebugLoc() const { return cast(Val)->hasMetadataOtherThanDebugLoc(); } /// Return true if this instruction has the given type of metadata attached. bool hasMetadata(unsigned KindID) const { return cast(Val)->hasMetadata(KindID); } // TODO: Implement getMetadata and getAllMetadata after sandboxir::MDNode is // available. // TODO: More missing functions /// Detach this from its parent BasicBlock without deleting it. LLVM_ABI void removeFromParent(); /// Detach this Value from its parent and delete it. LLVM_ABI void eraseFromParent(); /// Insert this detached instruction before \p BeforeI. LLVM_ABI void insertBefore(Instruction *BeforeI); /// Insert this detached instruction after \p AfterI. LLVM_ABI void insertAfter(Instruction *AfterI); /// Insert this detached instruction into \p BB at \p WhereIt. LLVM_ABI void insertInto(BasicBlock *BB, const BBIterator &WhereIt); /// Move this instruction to \p WhereIt. LLVM_ABI void moveBefore(BasicBlock &BB, const BBIterator &WhereIt); /// Move this instruction before \p Before. void moveBefore(Instruction *Before) { moveBefore(*Before->getParent(), Before->getIterator()); } /// Move this instruction after \p After. void moveAfter(Instruction *After) { moveBefore(*After->getParent(), std::next(After->getIterator())); } // TODO: This currently relies on LLVM IR Instruction::comesBefore which is // can be linear-time. /// Given an instruction Other in the same basic block as this instruction, /// return true if this instruction comes before Other. bool comesBefore(const Instruction *Other) const { return cast(Val)->comesBefore( cast(Other->Val)); } /// \Returns the BasicBlock containing this Instruction, or null if it is /// detached. LLVM_ABI BasicBlock *getParent() const; /// For isa/dyn_cast. LLVM_ABI static bool classof(const sandboxir::Value *From); /// Determine whether the no signed wrap flag is set. bool hasNoUnsignedWrap() const { return cast(Val)->hasNoUnsignedWrap(); } /// Set or clear the nuw flag on this instruction, which must be an operator /// which supports this flag. See LangRef.html for the meaning of this flag. LLVM_ABI void setHasNoUnsignedWrap(bool B = true); /// Determine whether the no signed wrap flag is set. bool hasNoSignedWrap() const { return cast(Val)->hasNoSignedWrap(); } /// Set or clear the nsw flag on this instruction, which must be an operator /// which supports this flag. See LangRef.html for the meaning of this flag. LLVM_ABI void setHasNoSignedWrap(bool B = true); /// Determine whether all fast-math-flags are set. bool isFast() const { return cast(Val)->isFast(); } /// Set or clear all fast-math-flags on this instruction, which must be an /// operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setFast(bool B); /// Determine whether the allow-reassociation flag is set. bool hasAllowReassoc() const { return cast(Val)->hasAllowReassoc(); } /// Set or clear the reassociation flag on this instruction, which must be /// an operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setHasAllowReassoc(bool B); /// Determine whether the exact flag is set. bool isExact() const { return cast(Val)->isExact(); } /// Set or clear the exact flag on this instruction, which must be an operator /// which supports this flag. See LangRef.html for the meaning of this flag. LLVM_ABI void setIsExact(bool B = true); /// Determine whether the no-NaNs flag is set. bool hasNoNaNs() const { return cast(Val)->hasNoNaNs(); } /// Set or clear the no-nans flag on this instruction, which must be an /// operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setHasNoNaNs(bool B); /// Determine whether the no-infs flag is set. bool hasNoInfs() const { return cast(Val)->hasNoInfs(); } /// Set or clear the no-infs flag on this instruction, which must be an /// operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setHasNoInfs(bool B); /// Determine whether the no-signed-zeros flag is set. bool hasNoSignedZeros() const { return cast(Val)->hasNoSignedZeros(); } /// Set or clear the no-signed-zeros flag on this instruction, which must be /// an operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setHasNoSignedZeros(bool B); /// Determine whether the allow-reciprocal flag is set. bool hasAllowReciprocal() const { return cast(Val)->hasAllowReciprocal(); } /// Set or clear the allow-reciprocal flag on this instruction, which must be /// an operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setHasAllowReciprocal(bool B); /// Determine whether the allow-contract flag is set. bool hasAllowContract() const { return cast(Val)->hasAllowContract(); } /// Set or clear the allow-contract flag on this instruction, which must be /// an operator which supports this flag. See LangRef.html for the meaning of /// this flag. LLVM_ABI void setHasAllowContract(bool B); /// Determine whether the approximate-math-functions flag is set. bool hasApproxFunc() const { return cast(Val)->hasApproxFunc(); } /// Set or clear the approximate-math-functions flag on this instruction, /// which must be an operator which supports this flag. See LangRef.html for /// the meaning of this flag. LLVM_ABI void setHasApproxFunc(bool B); /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of /// these flags. FastMathFlags getFastMathFlags() const { return cast(Val)->getFastMathFlags(); } /// Convenience function for setting multiple fast-math flags on this /// instruction, which must be an operator which supports these flags. See /// LangRef.html for the meaning of these flags. LLVM_ABI void setFastMathFlags(FastMathFlags FMF); /// Convenience function for transferring all fast-math flag values to this /// instruction, which must be an operator which supports these flags. See /// LangRef.html for the meaning of these flags. LLVM_ABI void copyFastMathFlags(FastMathFlags FMF); bool isAssociative() const { return cast(Val)->isAssociative(); } bool isCommutative() const { return cast(Val)->isCommutative(); } bool isIdempotent() const { return cast(Val)->isIdempotent(); } bool isNilpotent() const { return cast(Val)->isNilpotent(); } bool mayWriteToMemory() const { return cast(Val)->mayWriteToMemory(); } bool mayReadFromMemory() const { return cast(Val)->mayReadFromMemory(); } bool mayReadOrWriteMemory() const { return cast(Val)->mayReadOrWriteMemory(); } bool isAtomic() const { return cast(Val)->isAtomic(); } bool hasAtomicLoad() const { return cast(Val)->hasAtomicLoad(); } bool hasAtomicStore() const { return cast(Val)->hasAtomicStore(); } bool isVolatile() const { return cast(Val)->isVolatile(); } LLVM_ABI Type *getAccessType() const; bool mayThrow(bool IncludePhaseOneUnwind = false) const { return cast(Val)->mayThrow(IncludePhaseOneUnwind); } bool isFenceLike() const { return cast(Val)->isFenceLike(); } bool mayHaveSideEffects() const { return cast(Val)->mayHaveSideEffects(); } // TODO: Missing functions. #ifndef NDEBUG void dumpOS(raw_ostream &OS) const override; #endif }; /// Instructions that contain a single LLVM Instruction can inherit from this. template class SingleLLVMInstructionImpl : public Instruction { SingleLLVMInstructionImpl(ClassID ID, Opcode Opc, llvm::Instruction *I, sandboxir::Context &SBCtx) : Instruction(ID, Opc, I, SBCtx) {} // All instructions are friends with this so they can call the constructor. #define DEF_INSTR(ID, OPC, CLASS) friend class CLASS; #include "llvm/SandboxIR/Values.def" friend class UnaryInstruction; friend class CallBase; friend class FuncletPadInst; friend class CmpInst; Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { return getOperandUseDefault(OpIdx, Verify); } SmallVector getLLVMInstrs() const final { return {cast(Val)}; } public: unsigned getUseOperandNo(const Use &Use) const final { return getUseOperandNoDefault(Use); } unsigned getNumOfIRInstrs() const final { return 1u; } #ifndef NDEBUG void verify() const final { assert(isa(Val) && "Expected LLVMT!"); } void dumpOS(raw_ostream &OS) const override { dumpCommonPrefix(OS); dumpCommonSuffix(OS); } #endif }; class FenceInst : public SingleLLVMInstructionImpl { FenceInst(llvm::FenceInst *FI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Fence, Opcode::Fence, FI, Ctx) {} friend Context; // For constructor; public: LLVM_ABI static FenceInst *create(AtomicOrdering Ordering, InsertPosition Pos, Context &Ctx, SyncScope::ID SSID = SyncScope::System); /// Returns the ordering constraint of this fence instruction. AtomicOrdering getOrdering() const { return cast(Val)->getOrdering(); } /// Sets the ordering constraint of this fence instruction. May only be /// Acquire, Release, AcquireRelease, or SequentiallyConsistent. LLVM_ABI void setOrdering(AtomicOrdering Ordering); /// Returns the synchronization scope ID of this fence instruction. SyncScope::ID getSyncScopeID() const { return cast(Val)->getSyncScopeID(); } /// Sets the synchronization scope ID of this fence instruction. LLVM_ABI void setSyncScopeID(SyncScope::ID SSID); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Fence; } }; class SelectInst : public SingleLLVMInstructionImpl { /// Use Context::createSelectInst(). Don't call the /// constructor directly. SelectInst(llvm::SelectInst *CI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Select, Opcode::Select, CI, Ctx) {} friend Context; // for SelectInst() public: LLVM_ABI static Value *create(Value *Cond, Value *True, Value *False, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); const Value *getCondition() const { return getOperand(0); } const Value *getTrueValue() const { return getOperand(1); } const Value *getFalseValue() const { return getOperand(2); } Value *getCondition() { return getOperand(0); } Value *getTrueValue() { return getOperand(1); } Value *getFalseValue() { return getOperand(2); } void setCondition(Value *New) { setOperand(0, New); } void setTrueValue(Value *New) { setOperand(1, New); } void setFalseValue(Value *New) { setOperand(2, New); } LLVM_ABI void swapValues(); /// Return a string if the specified operands are invalid for a select /// operation, otherwise return null. static const char *areInvalidOperands(Value *Cond, Value *True, Value *False) { return llvm::SelectInst::areInvalidOperands(Cond->Val, True->Val, False->Val); } /// For isa/dyn_cast. LLVM_ABI static bool classof(const Value *From); }; class InsertElementInst final : public SingleLLVMInstructionImpl { /// Use Context::createInsertElementInst() instead. InsertElementInst(llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::InsertElement, Opcode::InsertElement, I, Ctx) {} friend class Context; // For accessing the constructor in create*() public: LLVM_ABI static Value *create(Value *Vec, Value *NewElt, Value *Idx, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::InsertElement; } static bool isValidOperands(const Value *Vec, const Value *NewElt, const Value *Idx) { return llvm::InsertElementInst::isValidOperands(Vec->Val, NewElt->Val, Idx->Val); } }; class ExtractElementInst final : public SingleLLVMInstructionImpl { /// Use Context::createExtractElementInst() instead. ExtractElementInst(llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::ExtractElement, Opcode::ExtractElement, I, Ctx) {} friend class Context; // For accessing the constructor in // create*() public: LLVM_ABI static Value *create(Value *Vec, Value *Idx, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::ExtractElement; } static bool isValidOperands(const Value *Vec, const Value *Idx) { return llvm::ExtractElementInst::isValidOperands(Vec->Val, Idx->Val); } Value *getVectorOperand() { return getOperand(0); } Value *getIndexOperand() { return getOperand(1); } const Value *getVectorOperand() const { return getOperand(0); } const Value *getIndexOperand() const { return getOperand(1); } LLVM_ABI VectorType *getVectorOperandType() const; }; class ShuffleVectorInst final : public SingleLLVMInstructionImpl { /// Use Context::createShuffleVectorInst() instead. ShuffleVectorInst(llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::ShuffleVector, Opcode::ShuffleVector, I, Ctx) {} friend class Context; // For accessing the constructor in create*() public: LLVM_ABI static Value *create(Value *V1, Value *V2, Value *Mask, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI static Value *create(Value *V1, Value *V2, ArrayRef Mask, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::ShuffleVector; } /// Swap the operands and adjust the mask to preserve the semantics of the /// instruction. LLVM_ABI void commute(); /// Return true if a shufflevector instruction can be formed with the /// specified operands. static bool isValidOperands(const Value *V1, const Value *V2, const Value *Mask) { return llvm::ShuffleVectorInst::isValidOperands(V1->Val, V2->Val, Mask->Val); } static bool isValidOperands(const Value *V1, const Value *V2, ArrayRef Mask) { return llvm::ShuffleVectorInst::isValidOperands(V1->Val, V2->Val, Mask); } /// Overload to return most specific vector type. LLVM_ABI VectorType *getType() const; /// Return the shuffle mask value of this instruction for the given element /// index. Return PoisonMaskElem if the element is undef. int getMaskValue(unsigned Elt) const { return cast(Val)->getMaskValue(Elt); } /// Convert the input shuffle mask operand to a vector of integers. Undefined /// elements of the mask are returned as PoisonMaskElem. static void getShuffleMask(const Constant *Mask, SmallVectorImpl &Result) { llvm::ShuffleVectorInst::getShuffleMask(cast(Mask->Val), Result); } /// Return the mask for this instruction as a vector of integers. Undefined /// elements of the mask are returned as PoisonMaskElem. void getShuffleMask(SmallVectorImpl &Result) const { cast(Val)->getShuffleMask(Result); } /// Return the mask for this instruction, for use in bitcode. LLVM_ABI Constant *getShuffleMaskForBitcode() const; LLVM_ABI static Constant *convertShuffleMaskForBitcode(ArrayRef Mask, Type *ResultTy); LLVM_ABI void setShuffleMask(ArrayRef Mask); ArrayRef getShuffleMask() const { return cast(Val)->getShuffleMask(); } /// Return true if this shuffle returns a vector with a different number of /// elements than its source vectors. /// Examples: shufflevector <4 x n> A, <4 x n> B, <1,2,3> /// shufflevector <4 x n> A, <4 x n> B, <1,2,3,4,5> bool changesLength() const { return cast(Val)->changesLength(); } /// Return true if this shuffle returns a vector with a greater number of /// elements than its source vectors. /// Example: shufflevector <2 x n> A, <2 x n> B, <1,2,3> bool increasesLength() const { return cast(Val)->increasesLength(); } /// Return true if this shuffle mask chooses elements from exactly one source /// vector. /// Example: <7,5,undef,7> /// This assumes that vector operands (of length \p NumSrcElts) are the same /// length as the mask. static bool isSingleSourceMask(ArrayRef Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isSingleSourceMask(Mask, NumSrcElts); } static bool isSingleSourceMask(const Constant *Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isSingleSourceMask( cast(Mask->Val), NumSrcElts); } /// Return true if this shuffle chooses elements from exactly one source /// vector without changing the length of that vector. /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3> bool isSingleSource() const { return cast(Val)->isSingleSource(); } /// Return true if this shuffle mask chooses elements from exactly one source /// vector without lane crossings. A shuffle using this mask is not /// necessarily a no-op because it may change the number of elements from its /// input vectors or it may provide demanded bits knowledge via undef lanes. /// Example: static bool isIdentityMask(ArrayRef Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isIdentityMask(Mask, NumSrcElts); } static bool isIdentityMask(const Constant *Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isIdentityMask( cast(Mask->Val), NumSrcElts); } /// Return true if this shuffle chooses elements from exactly one source /// vector without lane crossings and does not change the number of elements /// from its input vectors. /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef> bool isIdentity() const { return cast(Val)->isIdentity(); } /// Return true if this shuffle lengthens exactly one source vector with /// undefs in the high elements. bool isIdentityWithPadding() const { return cast(Val)->isIdentityWithPadding(); } /// Return true if this shuffle extracts the first N elements of exactly one /// source vector. bool isIdentityWithExtract() const { return cast(Val)->isIdentityWithExtract(); } /// Return true if this shuffle concatenates its 2 source vectors. This /// returns false if either input is undefined. In that case, the shuffle is /// is better classified as an identity with padding operation. bool isConcat() const { return cast(Val)->isConcat(); } /// Return true if this shuffle mask chooses elements from its source vectors /// without lane crossings. A shuffle using this mask would be /// equivalent to a vector select with a constant condition operand. /// Example: <4,1,6,undef> /// This returns false if the mask does not choose from both input vectors. /// In that case, the shuffle is better classified as an identity shuffle. /// This assumes that vector operands are the same length as the mask /// (a length-changing shuffle can never be equivalent to a vector select). static bool isSelectMask(ArrayRef Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isSelectMask(Mask, NumSrcElts); } static bool isSelectMask(const Constant *Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isSelectMask( cast(Mask->Val), NumSrcElts); } /// Return true if this shuffle chooses elements from its source vectors /// without lane crossings and all operands have the same number of elements. /// In other words, this shuffle is equivalent to a vector select with a /// constant condition operand. /// Example: shufflevector <4 x n> A, <4 x n> B, /// This returns false if the mask does not choose from both input vectors. /// In that case, the shuffle is better classified as an identity shuffle. bool isSelect() const { return cast(Val)->isSelect(); } /// Return true if this shuffle mask swaps the order of elements from exactly /// one source vector. /// Example: <7,6,undef,4> /// This assumes that vector operands (of length \p NumSrcElts) are the same /// length as the mask. static bool isReverseMask(ArrayRef Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isReverseMask(Mask, NumSrcElts); } static bool isReverseMask(const Constant *Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isReverseMask( cast(Mask->Val), NumSrcElts); } /// Return true if this shuffle swaps the order of elements from exactly /// one source vector. /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef> bool isReverse() const { return cast(Val)->isReverse(); } /// Return true if this shuffle mask chooses all elements with the same value /// as the first element of exactly one source vector. /// Example: <4,undef,undef,4> /// This assumes that vector operands (of length \p NumSrcElts) are the same /// length as the mask. static bool isZeroEltSplatMask(ArrayRef Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isZeroEltSplatMask(Mask, NumSrcElts); } static bool isZeroEltSplatMask(const Constant *Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isZeroEltSplatMask( cast(Mask->Val), NumSrcElts); } /// Return true if all elements of this shuffle are the same value as the /// first element of exactly one source vector without changing the length /// of that vector. /// Example: shufflevector <4 x n> A, <4 x n> B, bool isZeroEltSplat() const { return cast(Val)->isZeroEltSplat(); } /// Return true if this shuffle mask is a transpose mask. /// Transpose vector masks transpose a 2xn matrix. They read corresponding /// even- or odd-numbered vector elements from two n-dimensional source /// vectors and write each result into consecutive elements of an /// n-dimensional destination vector. Two shuffles are necessary to complete /// the transpose, one for the even elements and another for the odd elements. /// This description closely follows how the TRN1 and TRN2 AArch64 /// instructions operate. /// /// For example, a simple 2x2 matrix can be transposed with: /// /// ; Original matrix /// m0 = < a, b > /// m1 = < c, d > /// /// ; Transposed matrix /// t0 = < a, c > = shufflevector m0, m1, < 0, 2 > /// t1 = < b, d > = shufflevector m0, m1, < 1, 3 > /// /// For matrices having greater than n columns, the resulting nx2 transposed /// matrix is stored in two result vectors such that one vector contains /// interleaved elements from all the even-numbered rows and the other vector /// contains interleaved elements from all the odd-numbered rows. For example, /// a 2x4 matrix can be transposed with: /// /// ; Original matrix /// m0 = < a, b, c, d > /// m1 = < e, f, g, h > /// /// ; Transposed matrix /// t0 = < a, e, c, g > = shufflevector m0, m1 < 0, 4, 2, 6 > /// t1 = < b, f, d, h > = shufflevector m0, m1 < 1, 5, 3, 7 > static bool isTransposeMask(ArrayRef Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isTransposeMask(Mask, NumSrcElts); } static bool isTransposeMask(const Constant *Mask, int NumSrcElts) { return llvm::ShuffleVectorInst::isTransposeMask( cast(Mask->Val), NumSrcElts); } /// Return true if this shuffle transposes the elements of its inputs without /// changing the length of the vectors. This operation may also be known as a /// merge or interleave. See the description for isTransposeMask() for the /// exact specification. /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6> bool isTranspose() const { return cast(Val)->isTranspose(); } /// Return true if this shuffle mask is a splice mask, concatenating the two /// inputs together and then extracts an original width vector starting from /// the splice index. /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4> /// This assumes that vector operands (of length \p NumSrcElts) are the same /// length as the mask. static bool isSpliceMask(ArrayRef Mask, int NumSrcElts, int &Index) { return llvm::ShuffleVectorInst::isSpliceMask(Mask, NumSrcElts, Index); } static bool isSpliceMask(const Constant *Mask, int NumSrcElts, int &Index) { return llvm::ShuffleVectorInst::isSpliceMask( cast(Mask->Val), NumSrcElts, Index); } /// Return true if this shuffle splices two inputs without changing the length /// of the vectors. This operation concatenates the two inputs together and /// then extracts an original width vector starting from the splice index. /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4> bool isSplice(int &Index) const { return cast(Val)->isSplice(Index); } /// Return true if this shuffle mask is an extract subvector mask. /// A valid extract subvector mask returns a smaller vector from a single /// source operand. The base extraction index is returned as well. static bool isExtractSubvectorMask(ArrayRef Mask, int NumSrcElts, int &Index) { return llvm::ShuffleVectorInst::isExtractSubvectorMask(Mask, NumSrcElts, Index); } static bool isExtractSubvectorMask(const Constant *Mask, int NumSrcElts, int &Index) { return llvm::ShuffleVectorInst::isExtractSubvectorMask( cast(Mask->Val), NumSrcElts, Index); } /// Return true if this shuffle mask is an extract subvector mask. bool isExtractSubvectorMask(int &Index) const { return cast(Val)->isExtractSubvectorMask(Index); } /// Return true if this shuffle mask is an insert subvector mask. /// A valid insert subvector mask inserts the lowest elements of a second /// source operand into an in-place first source operand. /// Both the sub vector width and the insertion index is returned. static bool isInsertSubvectorMask(ArrayRef Mask, int NumSrcElts, int &NumSubElts, int &Index) { return llvm::ShuffleVectorInst::isInsertSubvectorMask(Mask, NumSrcElts, NumSubElts, Index); } static bool isInsertSubvectorMask(const Constant *Mask, int NumSrcElts, int &NumSubElts, int &Index) { return llvm::ShuffleVectorInst::isInsertSubvectorMask( cast(Mask->Val), NumSrcElts, NumSubElts, Index); } /// Return true if this shuffle mask is an insert subvector mask. bool isInsertSubvectorMask(int &NumSubElts, int &Index) const { return cast(Val)->isInsertSubvectorMask(NumSubElts, Index); } /// Return true if this shuffle mask replicates each of the \p VF elements /// in a vector \p ReplicationFactor times. /// For example, the mask for \p ReplicationFactor=3 and \p VF=4 is: /// <0,0,0,1,1,1,2,2,2,3,3,3> static bool isReplicationMask(ArrayRef Mask, int &ReplicationFactor, int &VF) { return llvm::ShuffleVectorInst::isReplicationMask(Mask, ReplicationFactor, VF); } static bool isReplicationMask(const Constant *Mask, int &ReplicationFactor, int &VF) { return llvm::ShuffleVectorInst::isReplicationMask( cast(Mask->Val), ReplicationFactor, VF); } /// Return true if this shuffle mask is a replication mask. bool isReplicationMask(int &ReplicationFactor, int &VF) const { return cast(Val)->isReplicationMask( ReplicationFactor, VF); } /// Return true if this shuffle mask represents "clustered" mask of size VF, /// i.e. each index between [0..VF) is used exactly once in each submask of /// size VF. /// For example, the mask for \p VF=4 is: /// 0, 1, 2, 3, 3, 2, 0, 1 - "clustered", because each submask of size 4 /// (0,1,2,3 and 3,2,0,1) uses indices [0..VF) exactly one time. /// 0, 1, 2, 3, 3, 3, 1, 0 - not "clustered", because /// element 3 is used twice in the second submask /// (3,3,1,0) and index 2 is not used at all. static bool isOneUseSingleSourceMask(ArrayRef Mask, int VF) { return llvm::ShuffleVectorInst::isOneUseSingleSourceMask(Mask, VF); } /// Return true if this shuffle mask is a one-use-single-source("clustered") /// mask. bool isOneUseSingleSourceMask(int VF) const { return cast(Val)->isOneUseSingleSourceMask(VF); } /// Change values in a shuffle permute mask assuming the two vector operands /// of length InVecNumElts have swapped position. static void commuteShuffleMask(MutableArrayRef Mask, unsigned InVecNumElts) { llvm::ShuffleVectorInst::commuteShuffleMask(Mask, InVecNumElts); } /// Return if this shuffle interleaves its two input vectors together. bool isInterleave(unsigned Factor) const { return cast(Val)->isInterleave(Factor); } /// Return true if the mask interleaves one or more input vectors together. /// /// I.e. <0, LaneLen, ... , LaneLen*(Factor - 1), 1, LaneLen + 1, ...> /// E.g. For a Factor of 2 (LaneLen=4): /// <0, 4, 1, 5, 2, 6, 3, 7> /// E.g. For a Factor of 3 (LaneLen=4): /// <4, 0, 9, 5, 1, 10, 6, 2, 11, 7, 3, 12> /// E.g. For a Factor of 4 (LaneLen=2): /// <0, 2, 6, 4, 1, 3, 7, 5> /// /// NumInputElts is the total number of elements in the input vectors. /// /// StartIndexes are the first indexes of each vector being interleaved, /// substituting any indexes that were undef /// E.g. <4, -1, 2, 5, 1, 3> (Factor=3): StartIndexes=<4, 0, 2> /// /// Note that this does not check if the input vectors are consecutive: /// It will return true for masks such as /// <0, 4, 6, 1, 5, 7> (Factor=3, LaneLen=2) static bool isInterleaveMask(ArrayRef Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl &StartIndexes) { return llvm::ShuffleVectorInst::isInterleaveMask(Mask, Factor, NumInputElts, StartIndexes); } static bool isInterleaveMask(ArrayRef Mask, unsigned Factor, unsigned NumInputElts) { return llvm::ShuffleVectorInst::isInterleaveMask(Mask, Factor, NumInputElts); } /// Check if the mask is a DE-interleave mask of the given factor /// \p Factor like: /// static bool isDeInterleaveMaskOfFactor(ArrayRef Mask, unsigned Factor, unsigned &Index) { return llvm::ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor, Index); } static bool isDeInterleaveMaskOfFactor(ArrayRef Mask, unsigned Factor) { return llvm::ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor); } /// Checks if the shuffle is a bit rotation of the first operand across /// multiple subelements, e.g: /// /// shuffle <8 x i8> %a, <8 x i8> poison, <8 x i32> <1, 0, 3, 2, 5, 4, 7, 6> /// /// could be expressed as /// /// rotl <4 x i16> %a, 8 /// /// If it can be expressed as a rotation, returns the number of subelements to /// group by in NumSubElts and the number of bits to rotate left in RotateAmt. static bool isBitRotateMask(ArrayRef Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt) { return llvm::ShuffleVectorInst::isBitRotateMask( Mask, EltSizeInBits, MinSubElts, MaxSubElts, NumSubElts, RotateAmt); } }; class InsertValueInst : public SingleLLVMInstructionImpl { /// Use Context::createInsertValueInst(). Don't call the constructor directly. InsertValueInst(llvm::InsertValueInst *IVI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::InsertValue, Opcode::InsertValue, IVI, Ctx) {} friend Context; // for InsertValueInst() public: LLVM_ABI static Value *create(Value *Agg, Value *Val, ArrayRef Idxs, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::InsertValue; } using idx_iterator = llvm::InsertValueInst::idx_iterator; inline idx_iterator idx_begin() const { return cast(Val)->idx_begin(); } inline idx_iterator idx_end() const { return cast(Val)->idx_end(); } inline iterator_range indices() const { return cast(Val)->indices(); } Value *getAggregateOperand() { return getOperand(getAggregateOperandIndex()); } const Value *getAggregateOperand() const { return getOperand(getAggregateOperandIndex()); } static unsigned getAggregateOperandIndex() { return llvm::InsertValueInst::getAggregateOperandIndex(); } Value *getInsertedValueOperand() { return getOperand(getInsertedValueOperandIndex()); } const Value *getInsertedValueOperand() const { return getOperand(getInsertedValueOperandIndex()); } static unsigned getInsertedValueOperandIndex() { return llvm::InsertValueInst::getInsertedValueOperandIndex(); } ArrayRef getIndices() const { return cast(Val)->getIndices(); } unsigned getNumIndices() const { return cast(Val)->getNumIndices(); } unsigned hasIndices() const { return cast(Val)->hasIndices(); } }; class BranchInst : public SingleLLVMInstructionImpl { /// Use Context::createBranchInst(). Don't call the constructor directly. BranchInst(llvm::BranchInst *BI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Br, Opcode::Br, BI, Ctx) {} friend Context; // for BranchInst() public: LLVM_ABI static BranchInst *create(BasicBlock *IfTrue, InsertPosition Pos, Context &Ctx); LLVM_ABI static BranchInst *create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, InsertPosition Pos, Context &Ctx); /// For isa/dyn_cast. LLVM_ABI static bool classof(const Value *From); bool isUnconditional() const { return cast(Val)->isUnconditional(); } bool isConditional() const { return cast(Val)->isConditional(); } LLVM_ABI Value *getCondition() const; void setCondition(Value *V) { setOperand(0, V); } unsigned getNumSuccessors() const { return 1 + isConditional(); } LLVM_ABI BasicBlock *getSuccessor(unsigned SuccIdx) const; LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *NewSucc); void swapSuccessors() { swapOperandsInternal(1, 2); } private: struct LLVMBBToSBBB { Context &Ctx; LLVMBBToSBBB(Context &Ctx) : Ctx(Ctx) {} LLVM_ABI BasicBlock *operator()(llvm::BasicBlock *BB) const; }; struct ConstLLVMBBToSBBB { Context &Ctx; ConstLLVMBBToSBBB(Context &Ctx) : Ctx(Ctx) {} LLVM_ABI const BasicBlock *operator()(const llvm::BasicBlock *BB) const; }; public: using sb_succ_op_iterator = mapped_iterator; iterator_range successors() { iterator_range LLVMRange = cast(Val)->successors(); LLVMBBToSBBB BBMap(Ctx); sb_succ_op_iterator MappedBegin = map_iterator(LLVMRange.begin(), BBMap); sb_succ_op_iterator MappedEnd = map_iterator(LLVMRange.end(), BBMap); return make_range(MappedBegin, MappedEnd); } using const_sb_succ_op_iterator = mapped_iterator; iterator_range successors() const { iterator_range ConstLLVMRange = static_cast(cast(Val)) ->successors(); ConstLLVMBBToSBBB ConstBBMap(Ctx); const_sb_succ_op_iterator ConstMappedBegin = map_iterator(ConstLLVMRange.begin(), ConstBBMap); const_sb_succ_op_iterator ConstMappedEnd = map_iterator(ConstLLVMRange.end(), ConstBBMap); return make_range(ConstMappedBegin, ConstMappedEnd); } }; /// An abstract class, parent of unary instructions. class UnaryInstruction : public SingleLLVMInstructionImpl { protected: UnaryInstruction(ClassID ID, Opcode Opc, llvm::Instruction *LLVMI, Context &Ctx) : SingleLLVMInstructionImpl(ID, Opc, LLVMI, Ctx) {} public: static bool classof(const Instruction *I) { return isa(I) || isa(I) || isa(I); } static bool classof(const Value *V) { return isa(V) && classof(cast(V)); } }; class ExtractValueInst : public UnaryInstruction { /// Use Context::createExtractValueInst() instead. ExtractValueInst(llvm::ExtractValueInst *EVI, Context &Ctx) : UnaryInstruction(ClassID::ExtractValue, Opcode::ExtractValue, EVI, Ctx) {} friend Context; // for ExtractValueInst() public: LLVM_ABI static Value *create(Value *Agg, ArrayRef Idxs, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::ExtractValue; } /// Returns the type of the element that would be extracted /// with an extractvalue instruction with the specified parameters. /// /// Null is returned if the indices are invalid for the specified type. LLVM_ABI static Type *getIndexedType(Type *Agg, ArrayRef Idxs); using idx_iterator = llvm::ExtractValueInst::idx_iterator; inline idx_iterator idx_begin() const { return cast(Val)->idx_begin(); } inline idx_iterator idx_end() const { return cast(Val)->idx_end(); } inline iterator_range indices() const { return cast(Val)->indices(); } Value *getAggregateOperand() { return getOperand(getAggregateOperandIndex()); } const Value *getAggregateOperand() const { return getOperand(getAggregateOperandIndex()); } static unsigned getAggregateOperandIndex() { return llvm::ExtractValueInst::getAggregateOperandIndex(); } ArrayRef getIndices() const { return cast(Val)->getIndices(); } unsigned getNumIndices() const { return cast(Val)->getNumIndices(); } unsigned hasIndices() const { return cast(Val)->hasIndices(); } }; class VAArgInst : public UnaryInstruction { VAArgInst(llvm::VAArgInst *FI, Context &Ctx) : UnaryInstruction(ClassID::VAArg, Opcode::VAArg, FI, Ctx) {} friend Context; // For constructor; public: LLVM_ABI static VAArgInst *create(Value *List, Type *Ty, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI Value *getPointerOperand(); const Value *getPointerOperand() const { return const_cast(this)->getPointerOperand(); } static unsigned getPointerOperandIndex() { return llvm::VAArgInst::getPointerOperandIndex(); } static bool classof(const Value *From) { return From->getSubclassID() == ClassID::VAArg; } }; class FreezeInst : public UnaryInstruction { FreezeInst(llvm::FreezeInst *FI, Context &Ctx) : UnaryInstruction(ClassID::Freeze, Opcode::Freeze, FI, Ctx) {} friend Context; // For constructor; public: LLVM_ABI static FreezeInst *create(Value *V, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Freeze; } }; class LoadInst final : public UnaryInstruction { /// Use LoadInst::create() instead of calling the constructor. LoadInst(llvm::LoadInst *LI, Context &Ctx) : UnaryInstruction(ClassID::Load, Opcode::Load, LI, Ctx) {} friend Context; // for LoadInst() public: /// Return true if this is a load from a volatile memory location. bool isVolatile() const { return cast(Val)->isVolatile(); } /// Specify whether this is a volatile load or not. LLVM_ABI void setVolatile(bool V); LLVM_ABI static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align, InsertPosition Pos, bool IsVolatile, Context &Ctx, const Twine &Name = ""); static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align, InsertPosition Pos, Context &Ctx, const Twine &Name = "") { return create(Ty, Ptr, Align, Pos, /*IsVolatile=*/false, Ctx, Name); } /// For isa/dyn_cast. LLVM_ABI static bool classof(const Value *From); LLVM_ABI Value *getPointerOperand() const; Align getAlign() const { return cast(Val)->getAlign(); } bool isUnordered() const { return cast(Val)->isUnordered(); } bool isSimple() const { return cast(Val)->isSimple(); } }; class StoreInst final : public SingleLLVMInstructionImpl { /// Use StoreInst::create(). StoreInst(llvm::StoreInst *SI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Store, Opcode::Store, SI, Ctx) {} friend Context; // for StoreInst() public: /// Return true if this is a store from a volatile memory location. bool isVolatile() const { return cast(Val)->isVolatile(); } /// Specify whether this is a volatile store or not. LLVM_ABI void setVolatile(bool V); LLVM_ABI static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align, InsertPosition Pos, bool IsVolatile, Context &Ctx); static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align, InsertPosition Pos, Context &Ctx) { return create(V, Ptr, Align, Pos, /*IsVolatile=*/false, Ctx); } /// For isa/dyn_cast. LLVM_ABI static bool classof(const Value *From); LLVM_ABI Value *getValueOperand() const; LLVM_ABI Value *getPointerOperand() const; Align getAlign() const { return cast(Val)->getAlign(); } bool isSimple() const { return cast(Val)->isSimple(); } bool isUnordered() const { return cast(Val)->isUnordered(); } }; class UnreachableInst final : public Instruction { /// Use UnreachableInst::create() instead of calling the constructor. UnreachableInst(llvm::UnreachableInst *I, Context &Ctx) : Instruction(ClassID::Unreachable, Opcode::Unreachable, I, Ctx) {} friend Context; Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final { return getOperandUseDefault(OpIdx, Verify); } SmallVector getLLVMInstrs() const final { return {cast(Val)}; } public: LLVM_ABI static UnreachableInst *create(InsertPosition Pos, Context &Ctx); LLVM_ABI static bool classof(const Value *From); unsigned getNumSuccessors() const { return 0; } unsigned getUseOperandNo(const Use &Use) const final { llvm_unreachable("UnreachableInst has no operands!"); } unsigned getNumOfIRInstrs() const final { return 1u; } }; class ReturnInst final : public SingleLLVMInstructionImpl { /// Use ReturnInst::create() instead of calling the constructor. ReturnInst(llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Ret, Opcode::Ret, I, Ctx) {} ReturnInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(SubclassID, Opcode::Ret, I, Ctx) {} friend class Context; // For accessing the constructor in create*() static ReturnInst *createCommon(Value *RetVal, IRBuilder<> &Builder, Context &Ctx); public: LLVM_ABI static ReturnInst *create(Value *RetVal, InsertPosition Pos, Context &Ctx); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Ret; } /// \Returns null if there is no return value. LLVM_ABI Value *getReturnValue() const; }; class CallBase : public SingleLLVMInstructionImpl { CallBase(ClassID ID, Opcode Opc, llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(ID, Opc, I, Ctx) {} friend class CallInst; // For constructor. friend class InvokeInst; // For constructor. friend class CallBrInst; // For constructor. public: static bool classof(const Value *From) { auto Opc = From->getSubclassID(); return Opc == Instruction::ClassID::Call || Opc == Instruction::ClassID::Invoke || Opc == Instruction::ClassID::CallBr; } LLVM_ABI FunctionType *getFunctionType() const; op_iterator data_operands_begin() { return op_begin(); } const_op_iterator data_operands_begin() const { return const_cast(this)->data_operands_begin(); } op_iterator data_operands_end() { auto *LLVMCB = cast(Val); auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin(); return op_begin() + Dist; } const_op_iterator data_operands_end() const { auto *LLVMCB = cast(Val); auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin(); return op_begin() + Dist; } iterator_range data_ops() { return make_range(data_operands_begin(), data_operands_end()); } iterator_range data_ops() const { return make_range(data_operands_begin(), data_operands_end()); } bool data_operands_empty() const { return data_operands_end() == data_operands_begin(); } unsigned data_operands_size() const { return std::distance(data_operands_begin(), data_operands_end()); } bool isDataOperand(Use U) const { assert(this == U.getUser() && "Only valid to query with a use of this instruction!"); return cast(Val)->isDataOperand(U.LLVMUse); } unsigned getDataOperandNo(Use U) const { assert(isDataOperand(U) && "Data operand # out of range!"); return cast(Val)->getDataOperandNo(U.LLVMUse); } /// Return the total number operands (not operand bundles) used by /// every operand bundle in this OperandBundleUser. unsigned getNumTotalBundleOperands() const { return cast(Val)->getNumTotalBundleOperands(); } op_iterator arg_begin() { return op_begin(); } const_op_iterator arg_begin() const { return op_begin(); } op_iterator arg_end() { return data_operands_end() - getNumTotalBundleOperands(); } const_op_iterator arg_end() const { return const_cast(this)->arg_end(); } iterator_range args() { return make_range(arg_begin(), arg_end()); } iterator_range args() const { return make_range(arg_begin(), arg_end()); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return arg_end() - arg_begin(); } Value *getArgOperand(unsigned OpIdx) const { assert(OpIdx < arg_size() && "Out of bounds!"); return getOperand(OpIdx); } void setArgOperand(unsigned OpIdx, Value *NewOp) { assert(OpIdx < arg_size() && "Out of bounds!"); setOperand(OpIdx, NewOp); } Use getArgOperandUse(unsigned Idx) const { assert(Idx < arg_size() && "Out of bounds!"); return getOperandUse(Idx); } Use getArgOperandUse(unsigned Idx) { assert(Idx < arg_size() && "Out of bounds!"); return getOperandUse(Idx); } bool isArgOperand(Use U) const { return cast(Val)->isArgOperand(U.LLVMUse); } unsigned getArgOperandNo(Use U) const { return cast(Val)->getArgOperandNo(U.LLVMUse); } bool hasArgument(const Value *V) const { return is_contained(args(), V); } LLVM_ABI Value *getCalledOperand() const; LLVM_ABI Use getCalledOperandUse() const; LLVM_ABI Function *getCalledFunction() const; bool isIndirectCall() const { return cast(Val)->isIndirectCall(); } bool isCallee(Use U) const { return cast(Val)->isCallee(U.LLVMUse); } LLVM_ABI Function *getCaller(); const Function *getCaller() const { return const_cast(this)->getCaller(); } bool isMustTailCall() const { return cast(Val)->isMustTailCall(); } bool isTailCall() const { return cast(Val)->isTailCall(); } Intrinsic::ID getIntrinsicID() const { return cast(Val)->getIntrinsicID(); } void setCalledOperand(Value *V) { getCalledOperandUse().set(V); } LLVM_ABI void setCalledFunction(Function *F); CallingConv::ID getCallingConv() const { return cast(Val)->getCallingConv(); } bool isInlineAsm() const { return cast(Val)->isInlineAsm(); } }; class CallInst : public CallBase { /// Use Context::createCallInst(). Don't call the /// constructor directly. CallInst(llvm::Instruction *I, Context &Ctx) : CallBase(ClassID::Call, Opcode::Call, I, Ctx) {} friend class Context; // For accessing the constructor in create*() friend class IntrinsicInst; // For constructor public: LLVM_ABI static CallInst *create(FunctionType *FTy, Value *Func, ArrayRef Args, InsertPosition Pos, Context &Ctx, const Twine &NameStr = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Call; } }; class InvokeInst final : public CallBase { /// Use Context::createInvokeInst(). Don't call the /// constructor directly. InvokeInst(llvm::Instruction *I, Context &Ctx) : CallBase(ClassID::Invoke, Opcode::Invoke, I, Ctx) {} friend class Context; // For accessing the constructor in // create*() public: LLVM_ABI static InvokeInst *create(FunctionType *FTy, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, InsertPosition Pos, Context &Ctx, const Twine &NameStr = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Invoke; } LLVM_ABI BasicBlock *getNormalDest() const; LLVM_ABI BasicBlock *getUnwindDest() const; LLVM_ABI void setNormalDest(BasicBlock *BB); LLVM_ABI void setUnwindDest(BasicBlock *BB); LLVM_ABI LandingPadInst *getLandingPadInst() const; LLVM_ABI BasicBlock *getSuccessor(unsigned SuccIdx) const; void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) { assert(SuccIdx < 2 && "Successor # out of range for invoke!"); if (SuccIdx == 0) setNormalDest(NewSucc); else setUnwindDest(NewSucc); } unsigned getNumSuccessors() const { return cast(Val)->getNumSuccessors(); } }; class CallBrInst final : public CallBase { /// Use Context::createCallBrInst(). Don't call the /// constructor directly. CallBrInst(llvm::Instruction *I, Context &Ctx) : CallBase(ClassID::CallBr, Opcode::CallBr, I, Ctx) {} friend class Context; // For accessing the constructor in // create*() public: LLVM_ABI static CallBrInst *create(FunctionType *FTy, Value *Func, BasicBlock *DefaultDest, ArrayRef IndirectDests, ArrayRef Args, InsertPosition Pos, Context &Ctx, const Twine &NameStr = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CallBr; } unsigned getNumIndirectDests() const { return cast(Val)->getNumIndirectDests(); } LLVM_ABI Value *getIndirectDestLabel(unsigned Idx) const; LLVM_ABI Value *getIndirectDestLabelUse(unsigned Idx) const; LLVM_ABI BasicBlock *getDefaultDest() const; LLVM_ABI BasicBlock *getIndirectDest(unsigned Idx) const; LLVM_ABI SmallVector getIndirectDests() const; LLVM_ABI void setDefaultDest(BasicBlock *BB); LLVM_ABI void setIndirectDest(unsigned Idx, BasicBlock *BB); LLVM_ABI BasicBlock *getSuccessor(unsigned Idx) const; unsigned getNumSuccessors() const { return cast(Val)->getNumSuccessors(); } }; class LandingPadInst : public SingleLLVMInstructionImpl { LandingPadInst(llvm::LandingPadInst *LP, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::LandingPad, Opcode::LandingPad, LP, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI static LandingPadInst *create(Type *RetTy, unsigned NumReservedClauses, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); /// Return 'true' if this landingpad instruction is a /// cleanup. I.e., it should be run when unwinding even if its landing pad /// doesn't catch the exception. bool isCleanup() const { return cast(Val)->isCleanup(); } /// Indicate that this landingpad instruction is a cleanup. LLVM_ABI void setCleanup(bool V); // TODO: We are not implementing addClause() because we have no way to revert // it for now. /// Get the value of the clause at index Idx. Use isCatch/isFilter to /// determine what type of clause this is. LLVM_ABI Constant *getClause(unsigned Idx) const; /// Return 'true' if the clause and index Idx is a catch clause. bool isCatch(unsigned Idx) const { return cast(Val)->isCatch(Idx); } /// Return 'true' if the clause and index Idx is a filter clause. bool isFilter(unsigned Idx) const { return cast(Val)->isFilter(Idx); } /// Get the number of clauses for this landing pad. unsigned getNumClauses() const { return cast(Val)->getNumOperands(); } // TODO: We are not implementing reserveClauses() because we can't revert it. static bool classof(const Value *From) { return From->getSubclassID() == ClassID::LandingPad; } }; class FuncletPadInst : public SingleLLVMInstructionImpl { FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(SubclassID, Opc, I, Ctx) {} friend class CatchPadInst; // For constructor. friend class CleanupPadInst; // For constructor. public: /// Return the number of funcletpad arguments. unsigned arg_size() const { return cast(Val)->arg_size(); } /// Return the outer EH-pad this funclet is nested within. /// /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst /// is a CatchPadInst. LLVM_ABI Value *getParentPad() const; LLVM_ABI void setParentPad(Value *ParentPad); /// Return the Idx-th funcletpad argument. LLVM_ABI Value *getArgOperand(unsigned Idx) const; /// Set the Idx-th funcletpad argument. LLVM_ABI void setArgOperand(unsigned Idx, Value *V); // TODO: Implement missing functions: arg_operands(). static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CatchPad || From->getSubclassID() == ClassID::CleanupPad; } }; class CatchPadInst : public FuncletPadInst { CatchPadInst(llvm::CatchPadInst *CPI, Context &Ctx) : FuncletPadInst(ClassID::CatchPad, Opcode::CatchPad, CPI, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI CatchSwitchInst *getCatchSwitch() const; // TODO: We have not implemented setCatchSwitch() because we can't revert it // for now, as there is no CatchPadInst member function that can undo it. LLVM_ABI static CatchPadInst *create(Value *ParentPad, ArrayRef Args, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CatchPad; } }; class CleanupPadInst : public FuncletPadInst { CleanupPadInst(llvm::CleanupPadInst *CPI, Context &Ctx) : FuncletPadInst(ClassID::CleanupPad, Opcode::CleanupPad, CPI, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI static CleanupPadInst *create(Value *ParentPad, ArrayRef Args, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CleanupPad; } }; class CatchReturnInst : public SingleLLVMInstructionImpl { CatchReturnInst(llvm::CatchReturnInst *CRI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::CatchRet, Opcode::CatchRet, CRI, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI static CatchReturnInst *create(CatchPadInst *CatchPad, BasicBlock *BB, InsertPosition Pos, Context &Ctx); LLVM_ABI CatchPadInst *getCatchPad() const; LLVM_ABI void setCatchPad(CatchPadInst *CatchPad); LLVM_ABI BasicBlock *getSuccessor() const; LLVM_ABI void setSuccessor(BasicBlock *NewSucc); unsigned getNumSuccessors() { return cast(Val)->getNumSuccessors(); } LLVM_ABI Value *getCatchSwitchParentPad() const; static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CatchRet; } }; class CleanupReturnInst : public SingleLLVMInstructionImpl { CleanupReturnInst(llvm::CleanupReturnInst *CRI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::CleanupRet, Opcode::CleanupRet, CRI, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI static CleanupReturnInst *create(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB, InsertPosition Pos, Context &Ctx); bool hasUnwindDest() const { return cast(Val)->hasUnwindDest(); } bool unwindsToCaller() const { return cast(Val)->unwindsToCaller(); } LLVM_ABI CleanupPadInst *getCleanupPad() const; LLVM_ABI void setCleanupPad(CleanupPadInst *CleanupPad); unsigned getNumSuccessors() const { return cast(Val)->getNumSuccessors(); } LLVM_ABI BasicBlock *getUnwindDest() const; LLVM_ABI void setUnwindDest(BasicBlock *NewDest); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CleanupRet; } }; class GetElementPtrInst final : public SingleLLVMInstructionImpl { /// Use Context::createGetElementPtrInst(). Don't call /// the constructor directly. GetElementPtrInst(llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::GetElementPtr, Opcode::GetElementPtr, I, Ctx) {} GetElementPtrInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx) : SingleLLVMInstructionImpl(SubclassID, Opcode::GetElementPtr, I, Ctx) {} friend class Context; // For accessing the constructor in // create*() public: LLVM_ABI static Value *create(Type *Ty, Value *Ptr, ArrayRef IdxList, InsertPosition Pos, Context &Ctx, const Twine &NameStr = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::GetElementPtr; } LLVM_ABI Type *getSourceElementType() const; LLVM_ABI Type *getResultElementType() const; unsigned getAddressSpace() const { return cast(Val)->getAddressSpace(); } inline op_iterator idx_begin() { return op_begin() + 1; } inline const_op_iterator idx_begin() const { return const_cast(this)->idx_begin(); } inline op_iterator idx_end() { return op_end(); } inline const_op_iterator idx_end() const { return const_cast(this)->idx_end(); } inline iterator_range indices() { return make_range(idx_begin(), idx_end()); } inline iterator_range indices() const { return const_cast(this)->indices(); } LLVM_ABI Value *getPointerOperand() const; static unsigned getPointerOperandIndex() { return llvm::GetElementPtrInst::getPointerOperandIndex(); } LLVM_ABI Type *getPointerOperandType() const; unsigned getPointerAddressSpace() const { return cast(Val)->getPointerAddressSpace(); } unsigned getNumIndices() const { return cast(Val)->getNumIndices(); } bool hasIndices() const { return cast(Val)->hasIndices(); } bool hasAllConstantIndices() const { return cast(Val)->hasAllConstantIndices(); } GEPNoWrapFlags getNoWrapFlags() const { return cast(Val)->getNoWrapFlags(); } bool isInBounds() const { return cast(Val)->isInBounds(); } bool hasNoUnsignedSignedWrap() const { return cast(Val)->hasNoUnsignedSignedWrap(); } bool hasNoUnsignedWrap() const { return cast(Val)->hasNoUnsignedWrap(); } bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { return cast(Val)->accumulateConstantOffset(DL, Offset); } // TODO: Add missing member functions. }; class CatchSwitchInst : public SingleLLVMInstructionImpl { CatchSwitchInst(llvm::CatchSwitchInst *CSI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::CatchSwitch, Opcode::CatchSwitch, CSI, Ctx) {} friend class Context; // For accessing the constructor in create*() public: LLVM_ABI static CatchSwitchInst * create(Value *ParentPad, BasicBlock *UnwindBB, unsigned NumHandlers, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI Value *getParentPad() const; LLVM_ABI void setParentPad(Value *ParentPad); bool hasUnwindDest() const { return cast(Val)->hasUnwindDest(); } bool unwindsToCaller() const { return cast(Val)->unwindsToCaller(); } LLVM_ABI BasicBlock *getUnwindDest() const; LLVM_ABI void setUnwindDest(BasicBlock *UnwindDest); unsigned getNumHandlers() const { return cast(Val)->getNumHandlers(); } private: static BasicBlock *handler_helper(Value *V) { return cast(V); } static const BasicBlock *handler_helper(const Value *V) { return cast(V); } public: using DerefFnTy = BasicBlock *(*)(Value *); using handler_iterator = mapped_iterator; using handler_range = iterator_range; using ConstDerefFnTy = const BasicBlock *(*)(const Value *); using const_handler_iterator = mapped_iterator; using const_handler_range = iterator_range; handler_iterator handler_begin() { op_iterator It = op_begin() + 1; if (hasUnwindDest()) ++It; return handler_iterator(It, DerefFnTy(handler_helper)); } const_handler_iterator handler_begin() const { const_op_iterator It = op_begin() + 1; if (hasUnwindDest()) ++It; return const_handler_iterator(It, ConstDerefFnTy(handler_helper)); } handler_iterator handler_end() { return handler_iterator(op_end(), DerefFnTy(handler_helper)); } const_handler_iterator handler_end() const { return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper)); } handler_range handlers() { return make_range(handler_begin(), handler_end()); } const_handler_range handlers() const { return make_range(handler_begin(), handler_end()); } LLVM_ABI void addHandler(BasicBlock *Dest); // TODO: removeHandler() cannot be reverted because there is no equivalent // addHandler() with a handler_iterator to specify the position. So we can't // implement it for now. unsigned getNumSuccessors() const { return getNumOperands() - 1; } BasicBlock *getSuccessor(unsigned Idx) const { assert(Idx < getNumSuccessors() && "Successor # out of range for catchswitch!"); return cast(getOperand(Idx + 1)); } void setSuccessor(unsigned Idx, BasicBlock *NewSucc) { assert(Idx < getNumSuccessors() && "Successor # out of range for catchswitch!"); setOperand(Idx + 1, NewSucc); } static bool classof(const Value *From) { return From->getSubclassID() == ClassID::CatchSwitch; } }; class ResumeInst : public SingleLLVMInstructionImpl { ResumeInst(llvm::ResumeInst *CSI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Resume, Opcode::Resume, CSI, Ctx) {} friend class Context; // For accessing the constructor in create*() public: LLVM_ABI static ResumeInst *create(Value *Exn, InsertPosition Pos, Context &Ctx); LLVM_ABI Value *getValue() const; unsigned getNumSuccessors() const { return cast(Val)->getNumSuccessors(); } static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Resume; } }; class SwitchInst : public SingleLLVMInstructionImpl { SwitchInst(llvm::SwitchInst *SI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Switch, Opcode::Switch, SI, Ctx) {} friend class Context; // For accessing the constructor in create*() public: static constexpr unsigned DefaultPseudoIndex = llvm::SwitchInst::DefaultPseudoIndex; LLVM_ABI static SwitchInst *create(Value *V, BasicBlock *Dest, unsigned NumCases, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI Value *getCondition() const; LLVM_ABI void setCondition(Value *V); LLVM_ABI BasicBlock *getDefaultDest() const; bool defaultDestUnreachable() const { return cast(Val)->defaultDestUnreachable(); } LLVM_ABI void setDefaultDest(BasicBlock *DefaultCase); unsigned getNumCases() const { return cast(Val)->getNumCases(); } template class CaseItImpl; // The template helps avoid code duplication for const and non-const // CaseHandle variants. template class CaseHandleImpl { Context &Ctx; // NOTE: We are not wrapping an LLVM CaseHande here because it is not // default-constructible. Instead we are wrapping the LLVM CaseIt // iterator, as we can always get an LLVM CaseHandle by de-referencing it. LLVMCaseItT LLVMCaseIt; template friend class CaseItImpl; public: CaseHandleImpl(Context &Ctx, LLVMCaseItT LLVMCaseIt) : Ctx(Ctx), LLVMCaseIt(LLVMCaseIt) {} LLVM_ABI_FOR_TEST ConstT *getCaseValue() const; LLVM_ABI_FOR_TEST BlockT *getCaseSuccessor() const; unsigned getCaseIndex() const { const auto &LLVMCaseHandle = *LLVMCaseIt; return LLVMCaseHandle.getCaseIndex(); } unsigned getSuccessorIndex() const { const auto &LLVMCaseHandle = *LLVMCaseIt; return LLVMCaseHandle.getSuccessorIndex(); } }; // The template helps avoid code duplication for const and non-const CaseIt // variants. template class CaseItImpl : public iterator_facade_base< CaseItImpl, std::random_access_iterator_tag, const CaseHandleImpl> { CaseHandleImpl CH; public: CaseItImpl(Context &Ctx, LLVMCaseItT It) : CH(Ctx, It) {} CaseItImpl(SwitchInst *SI, ptrdiff_t CaseNum) : CH(SI->getContext(), llvm::SwitchInst::CaseIt( cast(SI->Val), CaseNum)) {} CaseItImpl &operator+=(ptrdiff_t N) { CH.LLVMCaseIt += N; return *this; } CaseItImpl &operator-=(ptrdiff_t N) { CH.LLVMCaseIt -= N; return *this; } ptrdiff_t operator-(const CaseItImpl &Other) const { return CH.LLVMCaseIt - Other.CH.LLVMCaseIt; } bool operator==(const CaseItImpl &Other) const { return CH.LLVMCaseIt == Other.CH.LLVMCaseIt; } bool operator<(const CaseItImpl &Other) const { return CH.LLVMCaseIt < Other.CH.LLVMCaseIt; } const CaseHandleImpl &operator*() const { return CH; } }; using CaseHandle = CaseHandleImpl; using CaseIt = CaseItImpl; using ConstCaseHandle = CaseHandleImpl; using ConstCaseIt = CaseItImpl; /// Returns a read/write iterator that points to the first case in the /// SwitchInst. CaseIt case_begin() { return CaseIt(Ctx, cast(Val)->case_begin()); } ConstCaseIt case_begin() const { return ConstCaseIt(Ctx, cast(Val)->case_begin()); } /// Returns a read/write iterator that points one past the last in the /// SwitchInst. CaseIt case_end() { return CaseIt(Ctx, cast(Val)->case_end()); } ConstCaseIt case_end() const { return ConstCaseIt(Ctx, cast(Val)->case_end()); } /// Iteration adapter for range-for loops. iterator_range cases() { return make_range(case_begin(), case_end()); } iterator_range cases() const { return make_range(case_begin(), case_end()); } CaseIt case_default() { return CaseIt(Ctx, cast(Val)->case_default()); } ConstCaseIt case_default() const { return ConstCaseIt(Ctx, cast(Val)->case_default()); } CaseIt findCaseValue(const ConstantInt *C) { const llvm::ConstantInt *LLVMC = cast(C->Val); return CaseIt(Ctx, cast(Val)->findCaseValue(LLVMC)); } ConstCaseIt findCaseValue(const ConstantInt *C) const { const llvm::ConstantInt *LLVMC = cast(C->Val); return ConstCaseIt(Ctx, cast(Val)->findCaseValue(LLVMC)); } LLVM_ABI ConstantInt *findCaseDest(BasicBlock *BB); LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest); /// This method removes the specified case and its successor from the switch /// instruction. Note that this operation may reorder the remaining cases at /// index idx and above. /// Note: /// This action invalidates iterators for all cases following the one removed, /// including the case_end() iterator. It returns an iterator for the next /// case. LLVM_ABI CaseIt removeCase(CaseIt It); unsigned getNumSuccessors() const { return cast(Val)->getNumSuccessors(); } LLVM_ABI BasicBlock *getSuccessor(unsigned Idx) const; LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *NewSucc); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::Switch; } }; class UnaryOperator : public UnaryInstruction { static Opcode getUnaryOpcode(llvm::Instruction::UnaryOps UnOp) { switch (UnOp) { case llvm::Instruction::FNeg: return Opcode::FNeg; case llvm::Instruction::UnaryOpsEnd: llvm_unreachable("Bad UnOp!"); } llvm_unreachable("Unhandled UnOp!"); } UnaryOperator(llvm::UnaryOperator *UO, Context &Ctx) : UnaryInstruction(ClassID::UnOp, getUnaryOpcode(UO->getOpcode()), UO, Ctx) {} friend Context; // for constructor. public: LLVM_ABI static Value *create(Instruction::Opcode Op, Value *OpV, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV, Value *CopyFrom, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); /// For isa/dyn_cast. static bool classof(const Value *From) { return From->getSubclassID() == ClassID::UnOp; } }; class BinaryOperator : public SingleLLVMInstructionImpl { protected: static Opcode getBinOpOpcode(llvm::Instruction::BinaryOps BinOp) { switch (BinOp) { case llvm::Instruction::Add: return Opcode::Add; case llvm::Instruction::FAdd: return Opcode::FAdd; case llvm::Instruction::Sub: return Opcode::Sub; case llvm::Instruction::FSub: return Opcode::FSub; case llvm::Instruction::Mul: return Opcode::Mul; case llvm::Instruction::FMul: return Opcode::FMul; case llvm::Instruction::UDiv: return Opcode::UDiv; case llvm::Instruction::SDiv: return Opcode::SDiv; case llvm::Instruction::FDiv: return Opcode::FDiv; case llvm::Instruction::URem: return Opcode::URem; case llvm::Instruction::SRem: return Opcode::SRem; case llvm::Instruction::FRem: return Opcode::FRem; case llvm::Instruction::Shl: return Opcode::Shl; case llvm::Instruction::LShr: return Opcode::LShr; case llvm::Instruction::AShr: return Opcode::AShr; case llvm::Instruction::And: return Opcode::And; case llvm::Instruction::Or: return Opcode::Or; case llvm::Instruction::Xor: return Opcode::Xor; case llvm::Instruction::BinaryOpsEnd: llvm_unreachable("Bad BinOp!"); } llvm_unreachable("Unhandled BinOp!"); } BinaryOperator(llvm::BinaryOperator *BinOp, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::BinaryOperator, getBinOpOpcode(BinOp->getOpcode()), BinOp, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS, Value *RHS, Value *CopyFrom, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); /// For isa/dyn_cast. static bool classof(const Value *From) { return From->getSubclassID() == ClassID::BinaryOperator; } void swapOperands() { swapOperandsInternal(0, 1); } }; /// An or instruction, which can be marked as "disjoint", indicating that the /// inputs don't have a 1 in the same bit position. Meaning this instruction /// can also be treated as an add. class PossiblyDisjointInst : public BinaryOperator { public: LLVM_ABI void setIsDisjoint(bool B); bool isDisjoint() const { return cast(Val)->isDisjoint(); } /// For isa/dyn_cast. static bool classof(const Value *From) { return isa(From) && cast(From)->getOpcode() == Opcode::Or; } }; class AtomicRMWInst : public SingleLLVMInstructionImpl { AtomicRMWInst(llvm::AtomicRMWInst *Atomic, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::AtomicRMW, Instruction::Opcode::AtomicRMW, Atomic, Ctx) { } friend class Context; // For constructor. public: using BinOp = llvm::AtomicRMWInst::BinOp; BinOp getOperation() const { return cast(Val)->getOperation(); } static StringRef getOperationName(BinOp Op) { return llvm::AtomicRMWInst::getOperationName(Op); } static bool isFPOperation(BinOp Op) { return llvm::AtomicRMWInst::isFPOperation(Op); } void setOperation(BinOp Op) { cast(Val)->setOperation(Op); } Align getAlign() const { return cast(Val)->getAlign(); } LLVM_ABI void setAlignment(Align Align); bool isVolatile() const { return cast(Val)->isVolatile(); } LLVM_ABI void setVolatile(bool V); AtomicOrdering getOrdering() const { return cast(Val)->getOrdering(); } LLVM_ABI void setOrdering(AtomicOrdering Ordering); SyncScope::ID getSyncScopeID() const { return cast(Val)->getSyncScopeID(); } LLVM_ABI void setSyncScopeID(SyncScope::ID SSID); LLVM_ABI Value *getPointerOperand(); const Value *getPointerOperand() const { return const_cast(this)->getPointerOperand(); } LLVM_ABI Value *getValOperand(); const Value *getValOperand() const { return const_cast(this)->getValOperand(); } unsigned getPointerAddressSpace() const { return cast(Val)->getPointerAddressSpace(); } bool isFloatingPointOperation() const { return cast(Val)->isFloatingPointOperation(); } static bool classof(const Value *From) { return From->getSubclassID() == ClassID::AtomicRMW; } LLVM_ABI static AtomicRMWInst * create(BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, InsertPosition Pos, Context &Ctx, SyncScope::ID SSID = SyncScope::System, const Twine &Name = ""); }; class AtomicCmpXchgInst : public SingleLLVMInstructionImpl { AtomicCmpXchgInst(llvm::AtomicCmpXchgInst *Atomic, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::AtomicCmpXchg, Instruction::Opcode::AtomicCmpXchg, Atomic, Ctx) {} friend class Context; // For constructor. public: /// Return the alignment of the memory that is being allocated by the /// instruction. Align getAlign() const { return cast(Val)->getAlign(); } LLVM_ABI void setAlignment(Align Align); /// Return true if this is a cmpxchg from a volatile memory /// location. bool isVolatile() const { return cast(Val)->isVolatile(); } /// Specify whether this is a volatile cmpxchg. LLVM_ABI void setVolatile(bool V); /// Return true if this cmpxchg may spuriously fail. bool isWeak() const { return cast(Val)->isWeak(); } LLVM_ABI void setWeak(bool IsWeak); static bool isValidSuccessOrdering(AtomicOrdering Ordering) { return llvm::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering); } static bool isValidFailureOrdering(AtomicOrdering Ordering) { return llvm::AtomicCmpXchgInst::isValidFailureOrdering(Ordering); } AtomicOrdering getSuccessOrdering() const { return cast(Val)->getSuccessOrdering(); } LLVM_ABI void setSuccessOrdering(AtomicOrdering Ordering); AtomicOrdering getFailureOrdering() const { return cast(Val)->getFailureOrdering(); } LLVM_ABI void setFailureOrdering(AtomicOrdering Ordering); AtomicOrdering getMergedOrdering() const { return cast(Val)->getMergedOrdering(); } SyncScope::ID getSyncScopeID() const { return cast(Val)->getSyncScopeID(); } LLVM_ABI void setSyncScopeID(SyncScope::ID SSID); LLVM_ABI Value *getPointerOperand(); const Value *getPointerOperand() const { return const_cast(this)->getPointerOperand(); } LLVM_ABI Value *getCompareOperand(); const Value *getCompareOperand() const { return const_cast(this)->getCompareOperand(); } LLVM_ABI Value *getNewValOperand(); const Value *getNewValOperand() const { return const_cast(this)->getNewValOperand(); } /// Returns the address space of the pointer operand. unsigned getPointerAddressSpace() const { return cast(Val)->getPointerAddressSpace(); } LLVM_ABI static AtomicCmpXchgInst * create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, InsertPosition Pos, Context &Ctx, SyncScope::ID SSID = SyncScope::System, const Twine &Name = ""); static bool classof(const Value *From) { return From->getSubclassID() == ClassID::AtomicCmpXchg; } }; class AllocaInst final : public UnaryInstruction { AllocaInst(llvm::AllocaInst *AI, Context &Ctx) : UnaryInstruction(ClassID::Alloca, Instruction::Opcode::Alloca, AI, Ctx) {} friend class Context; // For constructor. public: LLVM_ABI static AllocaInst *create(Type *Ty, unsigned AddrSpace, InsertPosition Pos, Context &Ctx, Value *ArraySize = nullptr, const Twine &Name = ""); /// Return true if there is an allocation size parameter to the allocation /// instruction that is not 1. bool isArrayAllocation() const { return cast(Val)->isArrayAllocation(); } /// Get the number of elements allocated. For a simple allocation of a single /// element, this will return a constant 1 value. LLVM_ABI Value *getArraySize(); const Value *getArraySize() const { return const_cast(this)->getArraySize(); } /// Overload to return most specific pointer type. LLVM_ABI PointerType *getType() const; /// Return the address space for the allocation. unsigned getAddressSpace() const { return cast(Val)->getAddressSpace(); } /// Get allocation size in bytes. Returns std::nullopt if size can't be /// determined, e.g. in case of a VLA. std::optional getAllocationSize(const DataLayout &DL) const { return cast(Val)->getAllocationSize(DL); } /// Get allocation size in bits. Returns std::nullopt if size can't be /// determined, e.g. in case of a VLA. std::optional getAllocationSizeInBits(const DataLayout &DL) const { return cast(Val)->getAllocationSizeInBits(DL); } /// Return the type that is being allocated by the instruction. LLVM_ABI Type *getAllocatedType() const; /// for use only in special circumstances that need to generically /// transform a whole instruction (eg: IR linking and vectorization). LLVM_ABI void setAllocatedType(Type *Ty); /// Return the alignment of the memory that is being allocated by the /// instruction. Align getAlign() const { return cast(Val)->getAlign(); } LLVM_ABI void setAlignment(Align Align); /// Return true if this alloca is in the entry block of the function and is a /// constant size. If so, the code generator will fold it into the /// prolog/epilog code, so it is basically free. bool isStaticAlloca() const { return cast(Val)->isStaticAlloca(); } /// Return true if this alloca is used as an inalloca argument to a call. Such /// allocas are never considered static even if they are in the entry block. bool isUsedWithInAlloca() const { return cast(Val)->isUsedWithInAlloca(); } /// Specify whether this alloca is used to represent the arguments to a call. LLVM_ABI void setUsedWithInAlloca(bool V); static bool classof(const Value *From) { if (auto *I = dyn_cast(From)) return I->getSubclassID() == Instruction::ClassID::Alloca; return false; } }; class CastInst : public UnaryInstruction { static Opcode getCastOpcode(llvm::Instruction::CastOps CastOp) { switch (CastOp) { case llvm::Instruction::ZExt: return Opcode::ZExt; case llvm::Instruction::SExt: return Opcode::SExt; case llvm::Instruction::FPToUI: return Opcode::FPToUI; case llvm::Instruction::FPToSI: return Opcode::FPToSI; case llvm::Instruction::FPExt: return Opcode::FPExt; case llvm::Instruction::PtrToAddr: return Opcode::PtrToAddr; case llvm::Instruction::PtrToInt: return Opcode::PtrToInt; case llvm::Instruction::IntToPtr: return Opcode::IntToPtr; case llvm::Instruction::SIToFP: return Opcode::SIToFP; case llvm::Instruction::UIToFP: return Opcode::UIToFP; case llvm::Instruction::Trunc: return Opcode::Trunc; case llvm::Instruction::FPTrunc: return Opcode::FPTrunc; case llvm::Instruction::BitCast: return Opcode::BitCast; case llvm::Instruction::AddrSpaceCast: return Opcode::AddrSpaceCast; case llvm::Instruction::CastOpsEnd: llvm_unreachable("Bad CastOp!"); } llvm_unreachable("Unhandled CastOp!"); } /// Use Context::createCastInst(). Don't call the /// constructor directly. CastInst(llvm::CastInst *CI, Context &Ctx) : UnaryInstruction(ClassID::Cast, getCastOpcode(CI->getOpcode()), CI, Ctx) {} friend Context; // for SBCastInstruction() public: LLVM_ABI static Value *create(Type *DestTy, Opcode Op, Value *Operand, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); /// For isa/dyn_cast. LLVM_ABI static bool classof(const Value *From); LLVM_ABI Type *getSrcTy() const; LLVM_ABI Type *getDestTy() const; }; /// Instruction that can have a nneg flag (zext/uitofp). class PossiblyNonNegInst : public CastInst { public: bool hasNonNeg() const { return cast(Val)->hasNonNeg(); } LLVM_ABI void setNonNeg(bool B); /// For isa/dyn_cast. static bool classof(const Value *From) { if (auto *I = dyn_cast(From)) { switch (I->getOpcode()) { case Opcode::ZExt: case Opcode::UIToFP: return true; default: return false; } } return false; } }; // Helper class to simplify stamping out CastInst subclasses. template class CastInstImpl : public CastInst { public: static Value *create(Value *Src, Type *DestTy, InsertPosition Pos, Context &Ctx, const Twine &Name = "") { return CastInst::create(DestTy, Op, Src, Pos, Ctx, Name); } static bool classof(const Value *From) { if (auto *I = dyn_cast(From)) return I->getOpcode() == Op; return false; } }; class TruncInst final : public CastInstImpl {}; class ZExtInst final : public CastInstImpl {}; class SExtInst final : public CastInstImpl {}; class FPTruncInst final : public CastInstImpl {}; class FPExtInst final : public CastInstImpl {}; class UIToFPInst final : public CastInstImpl {}; class SIToFPInst final : public CastInstImpl {}; class FPToUIInst final : public CastInstImpl {}; class FPToSIInst final : public CastInstImpl {}; class IntToPtrInst final : public CastInstImpl { }; class PtrToAddrInst final : public CastInstImpl {}; class PtrToIntInst final : public CastInstImpl { }; class BitCastInst final : public CastInstImpl {}; class AddrSpaceCastInst final : public CastInstImpl { public: /// \Returns the pointer operand. Value *getPointerOperand() { return getOperand(0); } /// \Returns the pointer operand. const Value *getPointerOperand() const { return const_cast(this)->getPointerOperand(); } /// \Returns the operand index of the pointer operand. static unsigned getPointerOperandIndex() { return 0u; } /// \Returns the address space of the pointer operand. unsigned getSrcAddressSpace() const { return getPointerOperand()->getType()->getPointerAddressSpace(); } /// \Returns the address space of the result. unsigned getDestAddressSpace() const { return getType()->getPointerAddressSpace(); } }; class PHINode final : public SingleLLVMInstructionImpl { /// Use Context::createPHINode(). Don't call the constructor directly. PHINode(llvm::PHINode *PHI, Context &Ctx) : SingleLLVMInstructionImpl(ClassID::PHI, Opcode::PHI, PHI, Ctx) {} friend Context; // for PHINode() /// Helper for mapped_iterator. struct LLVMBBToBB { Context &Ctx; LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {} LLVM_ABI BasicBlock *operator()(llvm::BasicBlock *LLVMBB) const; }; public: LLVM_ABI static PHINode *create(Type *Ty, unsigned NumReservedValues, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); /// For isa/dyn_cast. LLVM_ABI static bool classof(const Value *From); using const_block_iterator = mapped_iterator; const_block_iterator block_begin() const { LLVMBBToBB BBGetter(Ctx); return const_block_iterator(cast(Val)->block_begin(), BBGetter); } const_block_iterator block_end() const { LLVMBBToBB BBGetter(Ctx); return const_block_iterator(cast(Val)->block_end(), BBGetter); } iterator_range blocks() const { return make_range(block_begin(), block_end()); } op_range incoming_values() { return operands(); } const_op_range incoming_values() const { return operands(); } unsigned getNumIncomingValues() const { return cast(Val)->getNumIncomingValues(); } LLVM_ABI Value *getIncomingValue(unsigned Idx) const; LLVM_ABI void setIncomingValue(unsigned Idx, Value *V); static unsigned getOperandNumForIncomingValue(unsigned Idx) { return llvm::PHINode::getOperandNumForIncomingValue(Idx); } static unsigned getIncomingValueNumForOperand(unsigned Idx) { return llvm::PHINode::getIncomingValueNumForOperand(Idx); } LLVM_ABI BasicBlock *getIncomingBlock(unsigned Idx) const; LLVM_ABI BasicBlock *getIncomingBlock(const Use &U) const; LLVM_ABI void setIncomingBlock(unsigned Idx, BasicBlock *BB); LLVM_ABI void addIncoming(Value *V, BasicBlock *BB); LLVM_ABI Value *removeIncomingValue(unsigned Idx); LLVM_ABI Value *removeIncomingValue(BasicBlock *BB); LLVM_ABI int getBasicBlockIndex(const BasicBlock *BB) const; LLVM_ABI Value *getIncomingValueForBlock(const BasicBlock *BB) const; LLVM_ABI Value *hasConstantValue() const; bool hasConstantOrUndefValue() const { return cast(Val)->hasConstantOrUndefValue(); } bool isComplete() const { return cast(Val)->isComplete(); } LLVM_ABI void replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New); LLVM_ABI void removeIncomingValueIf(function_ref Predicate); // TODO: Implement // void copyIncomingBlocks(iterator_range BBRange, // uint32_t ToIdx = 0) }; // Wraps a static function that takes a single Predicate parameter // LLVMValType should be the type of the wrapped class #define WRAP_STATIC_PREDICATE(FunctionName) \ static auto FunctionName(Predicate P) { return LLVMValType::FunctionName(P); } // Wraps a member function that takes no parameters // LLVMValType should be the type of the wrapped class #define WRAP_MEMBER(FunctionName) \ auto FunctionName() const { return cast(Val)->FunctionName(); } // Wraps both--a common idiom in the CmpInst classes #define WRAP_BOTH(FunctionName) \ WRAP_STATIC_PREDICATE(FunctionName) \ WRAP_MEMBER(FunctionName) class CmpInst : public SingleLLVMInstructionImpl { protected: using LLVMValType = llvm::CmpInst; /// Use Context::createCmpInst(). Don't call the constructor directly. CmpInst(llvm::CmpInst *CI, Context &Ctx, ClassID Id, Opcode Opc) : SingleLLVMInstructionImpl(Id, Opc, CI, Ctx) {} friend Context; // for CmpInst() LLVM_ABI static Value *createCommon(Value *Cond, Value *True, Value *False, const Twine &Name, IRBuilder<> &Builder, Context &Ctx); public: using Predicate = llvm::CmpInst::Predicate; LLVM_ABI static Value *create(Predicate Pred, Value *S1, Value *S2, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI static Value *createWithCopiedFlags(Predicate Pred, Value *S1, Value *S2, const Instruction *FlagsSource, InsertPosition Pos, Context &Ctx, const Twine &Name = ""); LLVM_ABI void setPredicate(Predicate P); LLVM_ABI void swapOperands(); WRAP_MEMBER(getPredicate); WRAP_BOTH(isFPPredicate); WRAP_BOTH(isIntPredicate); WRAP_STATIC_PREDICATE(getPredicateName); WRAP_BOTH(getInversePredicate); WRAP_BOTH(getOrderedPredicate); WRAP_BOTH(getUnorderedPredicate); WRAP_BOTH(getSwappedPredicate); WRAP_BOTH(isStrictPredicate); WRAP_BOTH(isNonStrictPredicate); WRAP_BOTH(getStrictPredicate); WRAP_BOTH(getNonStrictPredicate); WRAP_BOTH(getFlippedStrictnessPredicate); WRAP_MEMBER(isCommutative); WRAP_BOTH(isEquality); WRAP_BOTH(isRelational); WRAP_BOTH(isSigned); WRAP_BOTH(isTrueWhenEqual); WRAP_BOTH(isFalseWhenEqual); WRAP_BOTH(isUnsigned); WRAP_STATIC_PREDICATE(isOrdered); WRAP_STATIC_PREDICATE(isUnordered); /// Method for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *From) { return From->getSubclassID() == ClassID::ICmp || From->getSubclassID() == ClassID::FCmp; } /// Create a result type for fcmp/icmp LLVM_ABI static Type *makeCmpResultType(Type *OpndType); #ifndef NDEBUG void dumpOS(raw_ostream &OS) const override; LLVM_DUMP_METHOD void dump() const; #endif }; class ICmpInst : public CmpInst { /// Use Context::createICmpInst(). Don't call the constructor directly. ICmpInst(llvm::ICmpInst *CI, Context &Ctx) : CmpInst(CI, Ctx, ClassID::ICmp, Opcode::ICmp) {} friend class Context; // For constructor. using LLVMValType = llvm::ICmpInst; public: LLVM_ABI void swapOperands(); WRAP_BOTH(getSignedPredicate); WRAP_BOTH(getUnsignedPredicate); WRAP_BOTH(getFlippedSignednessPredicate); WRAP_BOTH(isEquality); WRAP_MEMBER(isCommutative); WRAP_MEMBER(isRelational); WRAP_STATIC_PREDICATE(isGT); WRAP_STATIC_PREDICATE(isLT); WRAP_STATIC_PREDICATE(isGE); WRAP_STATIC_PREDICATE(isLE); static std::optional isImpliedByMatchingCmp(CmpPredicate Pred1, CmpPredicate Pred2) { return llvm::ICmpInst::isImpliedByMatchingCmp(Pred1, Pred2); } static auto predicates() { return llvm::ICmpInst::predicates(); } static bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred) { return llvm::ICmpInst::compare(LHS, RHS, Pred); } static bool classof(const Value *From) { return From->getSubclassID() == ClassID::ICmp; } }; class FCmpInst : public CmpInst { /// Use Context::createFCmpInst(). Don't call the constructor directly. FCmpInst(llvm::FCmpInst *CI, Context &Ctx) : CmpInst(CI, Ctx, ClassID::FCmp, Opcode::FCmp) {} friend class Context; // For constructor. using LLVMValType = llvm::FCmpInst; public: LLVM_ABI void swapOperands(); WRAP_BOTH(isEquality); WRAP_MEMBER(isCommutative); WRAP_MEMBER(isRelational); static auto predicates() { return llvm::FCmpInst::predicates(); } static bool compare(const APFloat &LHS, const APFloat &RHS, FCmpInst::Predicate Pred) { return llvm::FCmpInst::compare(LHS, RHS, Pred); } static bool classof(const Value *From) { return From->getSubclassID() == ClassID::FCmp; } }; #undef WRAP_STATIC_PREDICATE #undef WRAP_MEMBER #undef WRAP_BOTH /// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to /// an OpaqueInstr. class OpaqueInst : public SingleLLVMInstructionImpl { OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx) : SingleLLVMInstructionImpl(ClassID::Opaque, Opcode::Opaque, I, Ctx) {} OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx) : SingleLLVMInstructionImpl(SubclassID, Opcode::Opaque, I, Ctx) {} friend class Context; // For constructor. public: static bool classof(const sandboxir::Value *From) { return From->getSubclassID() == ClassID::Opaque; } }; } // namespace llvm::sandboxir #endif // LLVM_SANDBOXIR_INSTRUCTION_H