From ebe69fe11e48d322045d5949c83283927a0d790b Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 23 Mar 2015 12:10:34 -0700 Subject: Update aosp/master LLVM for rebase to r230699. Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9 --- include/llvm/IR/Attributes.h | 5 + include/llvm/IR/BasicBlock.h | 12 +- include/llvm/IR/CFG.h | 26 +- include/llvm/IR/CallSite.h | 2 +- include/llvm/IR/Comdat.h | 2 +- include/llvm/IR/Constant.h | 4 +- include/llvm/IR/ConstantRange.h | 95 +- include/llvm/IR/Constants.h | 64 +- include/llvm/IR/DIBuilder.h | 118 ++- include/llvm/IR/DataLayout.h | 7 + include/llvm/IR/DebugInfo.h | 293 ++++-- include/llvm/IR/DebugInfoFlags.def | 36 + include/llvm/IR/DebugInfoMetadata.h | 1669 ++++++++++++++++++++++++++++++++ include/llvm/IR/DebugLoc.h | 98 +- include/llvm/IR/DerivedTypes.h | 30 +- include/llvm/IR/DiagnosticInfo.h | 3 + include/llvm/IR/Dominators.h | 49 + include/llvm/IR/Function.h | 42 +- include/llvm/IR/GVMaterializer.h | 4 + include/llvm/IR/GlobalAlias.h | 4 +- include/llvm/IR/GlobalObject.h | 2 +- include/llvm/IR/GlobalValue.h | 3 +- include/llvm/IR/GlobalVariable.h | 6 +- include/llvm/IR/IRBuilder.h | 71 +- include/llvm/IR/IRPrintingPasses.h | 4 +- include/llvm/IR/InlineAsm.h | 4 +- include/llvm/IR/InstIterator.h | 12 + include/llvm/IR/InstrTypes.h | 32 +- include/llvm/IR/Instruction.h | 6 +- include/llvm/IR/Instructions.h | 37 +- include/llvm/IR/IntrinsicInst.h | 54 +- include/llvm/IR/Intrinsics.h | 30 +- include/llvm/IR/Intrinsics.td | 69 ++ include/llvm/IR/IntrinsicsBPF.td | 22 + include/llvm/IR/IntrinsicsHexagon.td | 319 +++--- include/llvm/IR/IntrinsicsPowerPC.td | 177 ++++ include/llvm/IR/IntrinsicsR600.td | 3 + include/llvm/IR/IntrinsicsX86.td | 581 +++++++++-- include/llvm/IR/LLVMContext.h | 4 +- include/llvm/IR/LeakDetector.h | 92 -- include/llvm/IR/LegacyPassManager.h | 12 +- include/llvm/IR/LegacyPassManagers.h | 9 + include/llvm/IR/LegacyPassNameParser.h | 10 +- include/llvm/IR/MDBuilder.h | 8 + include/llvm/IR/Metadata.def | 99 ++ include/llvm/IR/Metadata.h | 947 +++++++++++++++--- include/llvm/IR/MetadataTracking.h | 99 ++ include/llvm/IR/Module.h | 55 +- include/llvm/IR/Operator.h | 22 +- include/llvm/IR/PassManager.h | 808 +++++++--------- include/llvm/IR/PassManagerInternal.h | 349 +++++++ include/llvm/IR/PatternMatch.h | 751 +++++++------- include/llvm/IR/Statepoint.h | 298 ++++++ include/llvm/IR/TrackingMDRef.h | 170 ++++ include/llvm/IR/Type.h | 3 + include/llvm/IR/TypeFinder.h | 1 + include/llvm/IR/Use.h | 2 +- include/llvm/IR/UseListOrder.h | 4 +- include/llvm/IR/User.h | 4 +- include/llvm/IR/Value.h | 64 +- include/llvm/IR/ValueHandle.h | 98 +- include/llvm/IR/ValueMap.h | 36 +- include/llvm/IR/Verifier.h | 4 +- 63 files changed, 6081 insertions(+), 1863 deletions(-) create mode 100644 include/llvm/IR/DebugInfoFlags.def create mode 100644 include/llvm/IR/DebugInfoMetadata.h create mode 100644 include/llvm/IR/IntrinsicsBPF.td delete mode 100644 include/llvm/IR/LeakDetector.h create mode 100644 include/llvm/IR/Metadata.def create mode 100644 include/llvm/IR/MetadataTracking.h create mode 100644 include/llvm/IR/PassManagerInternal.h create mode 100644 include/llvm/IR/Statepoint.h create mode 100644 include/llvm/IR/TrackingMDRef.h (limited to 'include/llvm/IR') diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 5ff48d6..443892b 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -282,6 +282,11 @@ public: AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; + /// \brief Add the dereferenceable attribute to the attribute set at the given + /// index. Since attribute sets are immutable, this returns a new set. + AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 7c7dd2c..185fc29 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -82,8 +82,8 @@ private: void setParent(Function *parent); friend class SymbolTableListTraits; - BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; - void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; + BasicBlock(const BasicBlock &) = delete; + void operator=(const BasicBlock &) = delete; /// \brief Constructor. /// @@ -208,6 +208,14 @@ public: return const_cast(this)->getUniquePredecessor(); } + /// Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. This method is analogous to + /// getUniquePredeccessor above. + BasicBlock *getUniqueSuccessor(); + const BasicBlock *getUniqueSuccessor() const { + return const_cast(this)->getUniqueSuccessor(); + } + //===--------------------------------------------------------------------===// /// Instruction iterator methods /// diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index c8be8bd..8476431 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -16,6 +16,7 @@ #define LLVM_IR_CFG_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -84,6 +85,8 @@ public: typedef PredIterator pred_iterator; typedef PredIterator const_pred_iterator; +typedef llvm::iterator_range pred_range; +typedef llvm::iterator_range pred_const_range; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { @@ -93,8 +96,15 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} inline const_pred_iterator pred_end(const BasicBlock *BB) { return const_pred_iterator(BB, true); } - - +inline bool pred_empty(const BasicBlock *BB) { + return pred_begin(BB) == pred_end(BB); +} +inline pred_range predecessors(BasicBlock *BB) { + return pred_range(pred_begin(BB), pred_end(BB)); +} +inline pred_const_range predecessors(const BasicBlock *BB) { + return pred_const_range(pred_begin(BB), pred_end(BB)); +} //===----------------------------------------------------------------------===// // BasicBlock succ_iterator definition @@ -244,6 +254,8 @@ public: typedef SuccIterator succ_iterator; typedef SuccIterator succ_const_iterator; +typedef llvm::iterator_range succ_range; +typedef llvm::iterator_range succ_const_range; inline succ_iterator succ_begin(BasicBlock *BB) { return succ_iterator(BB->getTerminator()); @@ -257,6 +269,16 @@ inline succ_iterator succ_end(BasicBlock *BB) { inline succ_const_iterator succ_end(const BasicBlock *BB) { return succ_const_iterator(BB->getTerminator(), true); } +inline bool succ_empty(const BasicBlock *BB) { + return succ_begin(BB) == succ_end(BB); +} +inline succ_range successors(BasicBlock *BB) { + return succ_range(succ_begin(BB), succ_end(BB)); +} +inline succ_const_range successors(const BasicBlock *BB) { + return succ_const_range(succ_begin(BB), succ_end(BB)); +} + template struct isPodLike > { static const bool value = isPodLike::value; diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index df08257..a4ea243 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -78,7 +78,7 @@ public: InstrTy *getInstruction() const { return I.getPointer(); } InstrTy *operator->() const { return I.getPointer(); } - LLVM_EXPLICIT operator bool() const { return I.getPointer(); } + explicit operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called. /// diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h index 3e77a77..4d4c15f 100644 --- a/include/llvm/IR/Comdat.h +++ b/include/llvm/IR/Comdat.h @@ -49,7 +49,7 @@ private: friend class Module; Comdat(); Comdat(SelectionKind SK, StringMapEntry *Name); - Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + Comdat(const Comdat &) = delete; // Points to the map in Module. StringMapEntry *Name; diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index d26991e..75499e0 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -39,8 +39,8 @@ namespace llvm { /// don't have to worry about the lifetime of the objects. /// @brief LLVM Constant Representation class Constant : public User { - void operator=(const Constant &) LLVM_DELETED_FUNCTION; - Constant(const Constant &) LLVM_DELETED_FUNCTION; + void operator=(const Constant &) = delete; + Constant(const Constant &) = delete; void anchor() override; protected: diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 3d39289..5e8cd34 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -37,7 +37,7 @@ namespace llvm { -/// ConstantRange - This class represents an range of values. +/// This class represents a range of values. /// class ConstantRange { APInt Lower, Upper; @@ -59,7 +59,7 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// makeICmpRegion - Produce the smallest range that contains all values that + /// Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value /// contained within Other. /// @@ -69,47 +69,46 @@ public: static ConstantRange makeICmpRegion(unsigned Pred, const ConstantRange &Other); - /// getLower - Return the lower value for this range... + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } - /// getUpper - Return the upper value for this range... + /// Return the upper value for this range. /// const APInt &getUpper() const { return Upper; } - /// getBitWidth - get the bit width of this ConstantRange + /// Get the bit width of this ConstantRange. /// uint32_t getBitWidth() const { return Lower.getBitWidth(); } - /// isFullSet - Return true if this set contains all of the elements possible - /// for this data-type + /// Return true if this set contains all of the elements possible + /// for this data-type. /// bool isFullSet() const; - /// isEmptySet - Return true if this set contains no members. + /// Return true if this set contains no members. /// bool isEmptySet() const; - /// isWrappedSet - Return true if this set wraps around the top of the range, - /// for example: [100, 8) + /// Return true if this set wraps around the top of the range. + /// For example: [100, 8). /// bool isWrappedSet() const; - /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of - /// its bitwidth, for example: i8 [120, 140). + /// Return true if this set wraps around the INT_MIN of + /// its bitwidth. For example: i8 [120, 140). /// bool isSignWrappedSet() const; - /// contains - Return true if the specified value is in the set. + /// Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; - /// contains - Return true if the other range is a subset of this one. + /// Return true if the other range is a subset of this one. /// bool contains(const ConstantRange &CR) const; - /// getSingleElement - If this set contains a single element, return it, - /// otherwise return null. + /// If this set contains a single element, return it, otherwise return null. /// const APInt *getSingleElement() const { if (Upper == Lower + 1) @@ -117,35 +116,31 @@ public: return nullptr; } - /// isSingleElement - Return true if this set contains exactly one member. + /// Return true if this set contains exactly one member. /// bool isSingleElement() const { return getSingleElement() != nullptr; } - /// getSetSize - Return the number of elements in this set. + /// Return the number of elements in this set. /// APInt getSetSize() const; - /// getUnsignedMax - Return the largest unsigned value contained in the - /// ConstantRange. + /// Return the largest unsigned value contained in the ConstantRange. /// APInt getUnsignedMax() const; - /// getUnsignedMin - Return the smallest unsigned value contained in the - /// ConstantRange. + /// Return the smallest unsigned value contained in the ConstantRange. /// APInt getUnsignedMin() const; - /// getSignedMax - Return the largest signed value contained in the - /// ConstantRange. + /// Return the largest signed value contained in the ConstantRange. /// APInt getSignedMax() const; - /// getSignedMin - Return the smallest signed value contained in the - /// ConstantRange. + /// Return the smallest signed value contained in the ConstantRange. /// APInt getSignedMin() const; - /// operator== - Return true if this range is equal to another range. + /// Return true if this range is equal to another range. /// bool operator==(const ConstantRange &CR) const { return Lower == CR.Lower && Upper == CR.Upper; @@ -154,15 +149,14 @@ public: return !operator==(CR); } - /// subtract - Subtract the specified constant from the endpoints of this - /// constant range. + /// Subtract the specified constant from the endpoints of this constant range. ConstantRange subtract(const APInt &CI) const; /// \brief Subtract the specified range from this range (aka relative /// complement of the sets). ConstantRange difference(const ConstantRange &CR) const; - /// intersectWith - Return the range that results from the intersection of + /// Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the /// smallest possible set size that does so. Because there may be two @@ -171,7 +165,7 @@ public: /// ConstantRange intersectWith(const ConstantRange &CR) const; - /// unionWith - Return the range that results from the union of this range + /// Return the range that results from the union of this range /// with another range. The resultant range is guaranteed to include the /// elements of both sets, but may contain more. For example, [3, 9) union /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included @@ -179,85 +173,84 @@ public: /// ConstantRange unionWith(const ConstantRange &CR) const; - /// zeroExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// zero extended to BitWidth. ConstantRange zeroExtend(uint32_t BitWidth) const; - /// signExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// sign extended to BitWidth. ConstantRange signExtend(uint32_t BitWidth) const; - /// truncate - Return a new range in the specified integer type, which must be + /// Return a new range in the specified integer type, which must be /// strictly smaller than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// truncated to the specified type. ConstantRange truncate(uint32_t BitWidth) const; - /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is zero extended, truncated, or left alone to make it that width. ConstantRange zextOrTrunc(uint32_t BitWidth) const; - /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is sign extended, truncated, or left alone to make it that width. ConstantRange sextOrTrunc(uint32_t BitWidth) const; - /// add - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an addition of a value in this range and a value in \p Other. ConstantRange add(const ConstantRange &Other) const; - /// sub - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a subtraction of a value in this range and a value in \p Other. ConstantRange sub(const ConstantRange &Other) const; - /// multiply - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a multiplication of a value in this range and a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange multiply(const ConstantRange &Other) const; - /// smax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a signed maximum of a value in this range and a value in \p Other. ConstantRange smax(const ConstantRange &Other) const; - /// umax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned maximum of a value in this range and a value in \p Other. ConstantRange umax(const ConstantRange &Other) const; - /// udiv - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned division of a value in this range and a value in /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; - /// binaryAnd - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-and of a value in this range by a value in \p Other. ConstantRange binaryAnd(const ConstantRange &Other) const; - /// binaryOr - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-or of a value in this range by a value in \p Other. ConstantRange binaryOr(const ConstantRange &Other) const; - /// shl - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange shl(const ConstantRange &Other) const; - /// lshr - Return a new range representing the possible values resulting - /// from a logical right shift of a value in this range and a value in - /// \p Other. + /// Return a new range representing the possible values resulting from a + /// logical right shift of a value in this range and a value in \p Other. ConstantRange lshr(const ConstantRange &Other) const; - /// inverse - Return a new range that is the logical not of the current set. + /// Return a new range that is the logical not of the current set. /// ConstantRange inverse() const; - /// print - Print out the bounds to a stream... + /// Print out the bounds to a stream. /// void print(raw_ostream &OS) const; - /// dump - Allow printing from a debugger easily... + /// Allow printing from a debugger easily. /// void dump() const; }; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 1b0e1b7..59be653 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -46,8 +46,8 @@ template struct ConstantAggrKeyType; /// @brief Class for constant integers. class ConstantInt : public Constant { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: @@ -228,8 +228,8 @@ public: class ConstantFP : public Constant { APFloat Val; void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantFP(const ConstantFP &) = delete; friend class LLVMContextImpl; protected: ConstantFP(Type *Ty, const APFloat& V); @@ -294,8 +294,8 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantAggregateZero(const ConstantAggregateZero &) = delete; protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} @@ -325,6 +325,9 @@ public: /// index. Constant *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// static bool classof(const Value *V) { @@ -338,7 +341,7 @@ public: /// class ConstantArray : public Constant { friend struct ConstantAggrKeyType; - ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; + ConstantArray(const ConstantArray &) = delete; protected: ConstantArray(ArrayType *T, ArrayRef Val); public: @@ -380,7 +383,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // class ConstantStruct : public Constant { friend struct ConstantAggrKeyType; - ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; + ConstantStruct(const ConstantStruct &) = delete; protected: ConstantStruct(StructType *T, ArrayRef Val); public: @@ -439,7 +442,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// class ConstantVector : public Constant { friend struct ConstantAggrKeyType; - ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; + ConstantVector(const ConstantVector &) = delete; protected: ConstantVector(VectorType *T, ArrayRef Val); public: @@ -488,8 +491,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantPointerNull(const ConstantPointerNull &) = delete; protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, @@ -539,8 +542,8 @@ class ConstantDataSequential : public Constant { /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataSequential(const ConstantDataSequential &) = delete; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} @@ -650,8 +653,8 @@ private: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataArray : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataArray(const ConstantDataArray &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) @@ -673,6 +676,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with array type with an element + /// count and element type of float with precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -702,8 +714,8 @@ public: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataVector : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataVector(const ConstantDataVector &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) @@ -725,6 +737,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with vector type with an element + /// count and element type of float with the precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. @@ -753,7 +774,7 @@ public: /// BlockAddress - The address of a basic block. /// class BlockAddress : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); public: @@ -1165,8 +1186,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + UndefValue(const UndefValue &) = delete; protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: @@ -1196,6 +1217,9 @@ public: /// index. UndefValue *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 3a50609..97a7b83 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" @@ -65,22 +66,34 @@ namespace llvm { Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value - SmallVector AllEnumTypes; - /// Use TrackingVH to collect RetainTypes, since they can be updated - /// later on. - SmallVector, 4> AllRetainTypes; - SmallVector AllSubprograms; - SmallVector AllGVs; - SmallVector, 4> AllImportedModules; + SmallVector AllEnumTypes; + /// Track the RetainTypes, since they can be updated later on. + SmallVector AllRetainTypes; + SmallVector AllSubprograms; + SmallVector AllGVs; + SmallVector AllImportedModules; + + /// \brief Track nodes that may be unresolved. + SmallVector UnresolvedNodes; + bool AllowUnresolvedNodes; /// Each subprogram's preserved local variables. - DenseMap>> PreservedVariables; + DenseMap> PreservedVariables; + + DIBuilder(const DIBuilder &) = delete; + void operator=(const DIBuilder &) = delete; - DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; + /// \brief Create a temporary. + /// + /// Create an \a temporary node and track it in \a UnresolvedNodes. + void trackIfUnresolved(MDNode *N); public: - explicit DIBuilder(Module &M); + /// \brief Construct a builder for a module. + /// + /// If \c AllowUnresolved, collect unresolved nodes attached to the module + /// in order to resolve cycles during \a finalize(). + explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; /// finalize - Construct any deferred debug info descriptors. @@ -159,8 +172,12 @@ namespace llvm { /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); + DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. @@ -316,13 +333,8 @@ namespace llvm { /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. DITemplateTypeParameter - createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -330,40 +342,30 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val Constant parameter value. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - Constant *Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, + StringRef Name, + DIType Ty, + Constant *Val); /// \brief Create debugging information for a template template parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val The fully qualified name of the template. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, StringRef Val, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, + StringRef Name, + DIType Ty, + StringRef Val); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val An array of types in the pack. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateParameterPack(DIDescriptor Scope, StringRef Name, - DIType Ty, DIArray Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, + StringRef Name, + DIType Ty, + DIArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. @@ -423,10 +425,11 @@ namespace llvm { StringRef UniqueIdentifier = StringRef()); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableForwardDecl( + DICompositeType createReplaceableCompositeType( unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + uint64_t AlignInBits = 0, unsigned Flags = DIDescriptor::FlagFwdDecl, + StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -437,10 +440,10 @@ namespace llvm { DIBasicType createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef Elements); + DIArray getOrCreateArray(ArrayRef Elements); /// getOrCreateTypeArray - Get a DITypeArray, create one if required. - DITypeArray getOrCreateTypeArray(ArrayRef Elements); + DITypeArray getOrCreateTypeArray(ArrayRef Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. @@ -497,15 +500,16 @@ namespace llvm { /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Addr An array of complex address operations. - DIExpression createExpression(ArrayRef Addr = None); + DIExpression createExpression(ArrayRef Addr = None); + DIExpression createExpression(ArrayRef Addr); - /// createPieceExpression - Create a descriptor to describe one part + /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBytes Offset of the piece in bytes. - /// @param SizeInBytes Size of the piece in bytes. - DIExpression createPieceExpression(unsigned OffsetInBytes, - unsigned SizeInBytes); + /// @param OffsetInBits Offset of the piece in bits. + /// @param SizeInBits Size of the piece in bits. + DIExpression createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. @@ -685,6 +689,20 @@ namespace llvm { Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, DIExpression Expr, Instruction *InsertBefore); + + /// \brief Replace the vtable holder in the given composite type. + /// + /// If this creates a self reference, it may orphan some unresolved cycles + /// in the operands of \c T, so \a DIBuilder needs to track that. + void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + + /// \brief Replace arrays on a composite type. + /// + /// If \c T is resolved, but the arrays aren't -- which can happen if \c T + /// has a self-reference -- \a DIBuilder needs to track the array to + /// resolve cycles. + void replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParems = DIArray()); }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 4580a4f..9479ba4 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -53,6 +53,11 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a' }; +// FIXME: Currently the DataLayout string carries a "preferred alignment" +// for types. As the DataLayout is module/global, this should likely be +// sunk down to an FTTI element that is queried rather than a global +// preference. + /// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, @@ -228,6 +233,8 @@ public: return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); } + unsigned getStackAlignment() const { return StackNaturalAlign; } + bool hasMicrosoftFastStdCallMangling() const { return ManglingMode == MM_WINCOFF; } diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 22a2138..d2e5975 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -18,11 +18,11 @@ #define LLVM_IR_DEBUGINFO_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -66,10 +66,10 @@ class DIHeaderFieldIterator public: DIHeaderFieldIterator() {} - DIHeaderFieldIterator(StringRef Header) + explicit DIHeaderFieldIterator(StringRef Header) : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} StringRef operator*() const { return Current; } - const StringRef * operator->() const { return &Current; } + const StringRef *operator->() const { return &Current; } DIHeaderFieldIterator &operator++() { increment(); return *this; @@ -99,6 +99,16 @@ public: return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); } + /// \brief Get the current field as a number. + /// + /// Convert the current field into a number. Return \c 0 on error. + template T getNumber() const { + T Int; + if (getCurrent().getAsInteger(0, Int)) + return 0; + return Int; + } + private: void increment() { assert(Current.data() != nullptr && "Cannot increment past the end"); @@ -122,27 +132,21 @@ public: /// The three accessibility flags are mutually exclusive and rolled together /// in the first two bits. enum { - FlagAccessibility = 1 << 0 | 1 << 1, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic }; + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl &SplitFlags); + protected: const MDNode *DbgNode; @@ -168,42 +172,47 @@ public: bool Verify() const; - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator->() const { return const_cast(DbgNode); } + MDNode *get() const { return const_cast(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } // An explicit operator bool so that we can do testing of DI values // easily. // FIXME: This operator bool isn't actually protecting anything at the // moment due to the conversion operator above making DIDescriptor nodes // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; } + explicit operator bool() const { return DbgNode != nullptr; } bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - StringRef getHeader() const { - return getStringField(0); - } + StringRef getHeader() const { return getStringField(0); } size_t getNumHeaderFields() const { return std::distance(DIHeaderFieldIterator(getHeader()), DIHeaderFieldIterator()); } - StringRef getHeaderField(unsigned Index) const { + DIHeaderFieldIterator header_begin() const { + return DIHeaderFieldIterator(getHeader()); + } + DIHeaderFieldIterator header_end() const { return DIHeaderFieldIterator(); } + + DIHeaderFieldIterator getHeaderIterator(unsigned Index) const { // Since callers expect an empty string for out-of-range accesses, we can't // use std::advance() here. - for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) + for (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) if (!Index) - return *I; - return StringRef(); + return I; + return header_end(); + } + + StringRef getHeaderField(unsigned Index) const { + return *getHeaderIterator(Index); } template T getHeaderFieldAs(unsigned Index) const { - T Int; - if (getHeaderField(Index).getAsInteger(0, Int)) - return 0; - return Int; + return getHeaderIterator(Index).getNumber(); } uint16_t getTag() const { return getHeaderFieldAs(0); } @@ -238,6 +247,19 @@ public: void replaceAllUsesWith(MDNode *D); }; +#define RETURN_FROM_RAW(VALID, DEFAULT) \ + do { \ + if (auto *N = getRaw()) \ + return VALID; \ + return DEFAULT; \ + } while (false) +#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ + do { \ + if (auto *N = getRaw()) \ + return DESC(dyn_cast_or_null(VALID)); \ + return DESC(static_cast(nullptr)); \ + } while (false) + /// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; @@ -258,9 +280,7 @@ public: unsigned getNumElements() const { return DbgNode ? DbgNode->getNumOperands() : 0; } - T getElement(unsigned Idx) const { - return getFieldAs(Idx); - } + T getElement(unsigned Idx) const { return getFieldAs(Idx); } }; typedef DITypedArray DIArray; @@ -282,6 +302,7 @@ public: }; template class DIRef; +typedef DIRef DIDescriptorRef; typedef DIRef DIScopeRef; typedef DIRef DITypeRef; typedef DITypedArray DITypeArray; @@ -371,6 +392,12 @@ template StringRef DIRef::getName() const { return MS->getString(); } +/// \brief Handle fields that are references to DIDescriptors. +template <> +DIDescriptorRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// \brief Specialize DIRef constructor for DIDescriptorRef. +template <> DIRef::DIRef(const Metadata *V); + /// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; /// \brief Specialize DIRef constructor for DIScopeRef. @@ -381,7 +408,7 @@ template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const; /// \brief Specialize DIRef constructor for DITypeRef. template <> DIRef::DIRef(const Metadata *V); -/// \briefThis is a wrapper for a type. +/// \brief This is a wrapper for a type. /// /// FIXME: Types should be factored much better so that CV qualifiers and /// others do not require a huge and empty descriptor full of zeros. @@ -392,7 +419,7 @@ protected: public: explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { + operator DITypeRef() const { assert(isType() && "constructing DITypeRef from an MDNode that is not a type"); return DITypeRef(&*getRef()); @@ -402,20 +429,12 @@ public: DIScopeRef getContext() const { return getFieldAs(2); } StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - return getHeaderFieldAs(2); - } - uint64_t getSizeInBits() const { - return getHeaderFieldAs(3); - } - uint64_t getAlignInBits() const { - return getHeaderFieldAs(4); - } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } + uint64_t getSizeInBits() const { return getHeaderFieldAs(3); } + uint64_t getAlignInBits() const { return getHeaderFieldAs(4); } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { - return getHeaderFieldAs(5); - } + uint64_t getOffsetInBits() const { return getHeaderFieldAs(5); } unsigned getFlags() const { return getHeaderFieldAs(6); } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; @@ -499,6 +518,7 @@ public: // FIXME: Make this derive from DIType directly & just store the // base type in a single DIType field. class DICompositeType : public DIDerivedType { + friend class DIBuilder; friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -512,20 +532,26 @@ public: assert(!isSubroutineType() && "no elements for DISubroutineType"); return getFieldAs(4); } + +private: template void setArrays(DITypedArray Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); + assert( + (!TParams || DbgNode->getNumOperands() == 8) && + "If you're setting the template parameters this should include a slot " + "for that!"); setArraysHelper(Elements, TParams); } - unsigned getRunTimeLang() const { - return getHeaderFieldAs(7); - } + +public: + unsigned getRunTimeLang() const { return getHeaderFieldAs(7); } DITypeRef getContainingType() const { return getFieldAs(5); } +private: /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); + +public: DIArray getTemplateParams() const { return getFieldAs(6); } MDString *getIdentifier() const; @@ -663,7 +689,6 @@ public: unsigned isRValueReference() const { return (getFlags() & FlagRValueReference) != 0; } - }; /// \brief This is a wrapper for a lexical block. @@ -671,12 +696,8 @@ class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs(2); } - unsigned getLineNumber() const { - return getHeaderFieldAs(1); - } - unsigned getColumnNumber() const { - return getHeaderFieldAs(2); - } + unsigned getLineNumber() const { return getHeaderFieldAs(1); } + unsigned getColumnNumber() const { return getHeaderFieldAs(2); } bool Verify() const; }; @@ -685,6 +706,8 @@ class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { + // FIXME: This logic is horrible. getScope() returns a DILexicalBlock, but + // then we check if it's a subprogram? WHAT?!? if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); @@ -713,18 +736,11 @@ public: class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs(3); } - DIScopeRef getContext() const { return getFieldAs(1); } DITypeRef getType() const { return getFieldAs(2); } - StringRef getFilename() const { return getFieldAs(3).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(3).getDirectory(); - } bool Verify() const; }; @@ -732,19 +748,12 @@ public: class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs(3); } - DIScopeRef getContext() const { return getFieldAs(1); } DITypeRef getType() const { return getFieldAs(2); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(4).getDirectory(); - } + Metadata *getValue() const; bool Verify() const; }; @@ -763,7 +772,7 @@ public: unsigned isLocalToUnit() const { return getHeaderFieldAs(5); } unsigned isDefinition() const { return getHeaderFieldAs(6); } - DIScopeRef getContext() const { return getFieldAs(1); } + DIScope getContext() const { return getFieldAs(1); } StringRef getFilename() const { return getFieldAs(2).getFilename(); } StringRef getDirectory() const { return getFieldAs(2).getDirectory(); @@ -807,11 +816,6 @@ public: return (getHeaderFieldAs(3) & FlagObjectPointer) != 0; } - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getHeaderFieldAs(3) & FlagIndirectVariable) != 0; - } - /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; @@ -831,7 +835,13 @@ public: void printExtendedName(raw_ostream &OS) const; }; -/// \brief A complex location expression. +/// \brief A complex location expression in postfix notation. +/// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. class DIExpression : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -854,24 +864,91 @@ public: uint64_t getElement(unsigned Idx) const; /// \brief Return whether this is a piece of an aggregate variable. - bool isVariablePiece() const; - /// \brief Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// \brief Return the size of this piece in bytes. - uint64_t getPieceSize() const; + bool isBitPiece() const; + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + + class iterator; + /// \brief A lightweight wrapper around an element of a DIExpression. + class Operand { + friend class iterator; + DIHeaderFieldIterator I; + Operand() {} + Operand(DIHeaderFieldIterator I) : I(I) {} + public: + /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments. + /// Argument 0 is the operand itself. + uint64_t getArg(unsigned N) const { + DIHeaderFieldIterator In = I; + std::advance(In, N); + return In.getNumber(); + } + operator uint64_t () const { return I.getNumber(); } + /// \brief Returns underlying DIHeaderFieldIterator. + const DIHeaderFieldIterator &getBase() const { return I; } + /// \brief Returns the next operand. + Operand getNext() const; + }; + + /// \brief An iterator for DIExpression elements. + class iterator : public std::iterator { + friend class Operand; + DIHeaderFieldIterator I; + Operand Tmp; + iterator(DIHeaderFieldIterator I) : I(I) {} + public: + iterator() {} + iterator(const DIExpression &Expr) : I(++Expr.header_begin()) {} + const Operand &operator*() { return Tmp = Operand(I); } + const Operand *operator->() { return &(Tmp = Operand(I)); } + iterator &operator++() { + increment(); + return *this; + } + iterator operator++(int) { + iterator X(*this); + increment(); + return X; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return !(*this == X); } + + private: + void increment() { + switch (**this) { + case dwarf::DW_OP_bit_piece: std::advance(I, 3); break; + case dwarf::DW_OP_plus: std::advance(I, 2); break; + case dwarf::DW_OP_deref: std::advance(I, 1); break; + default: + llvm_unreachable("unsupported operand"); + } + } + }; + + iterator begin() const; + iterator end() const; }; /// \brief This object holds location information. /// /// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { + MDLocation *getRaw() const { return dyn_cast_or_null(get()); } + public: explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs(2); } - DILocation getOrigLocation() const { return getFieldAs(3); } + unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } + unsigned getColumnNumber() const { RETURN_FROM_RAW(N->getColumn(), 0); } + DIScope getScope() const { + RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); + } + DILocation getOrigLocation() const { + RETURN_DESCRIPTOR_FROM_RAW(DILocation, N->getInlinedAt()); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -892,7 +969,9 @@ public: // sure this location is a lexical block before retrieving its // value. return getScope().isLexicalBlockFile() - ? getFieldAs(2).getDiscriminator() + ? DILexicalBlockFile( + cast(cast(DbgNode)->getScope())) + .getDiscriminator() : 0; } @@ -951,14 +1030,18 @@ class DIImportedEntity : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: + DIImportedEntity() = default; explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs(1); } - DIScopeRef getEntity() const { return getFieldAs(2); } + DIDescriptorRef getEntity() const { return getFieldAs(2); } unsigned getLineNumber() const { return getHeaderFieldAs(1); } StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; +#undef RETURN_FROM_RAW +#undef RETURN_DESCRIPTOR_FROM_RAW + /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1015,6 +1098,9 @@ public: /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); + /// \brief Process DIExpression. + void processExpression(DIExpression Expr); + /// \brief Clear all lists. void reset(); @@ -1033,7 +1119,8 @@ private: public: typedef SmallVectorImpl::const_iterator compile_unit_iterator; typedef SmallVectorImpl::const_iterator subprogram_iterator; - typedef SmallVectorImpl::const_iterator global_variable_iterator; + typedef SmallVectorImpl::const_iterator + global_variable_iterator; typedef SmallVectorImpl::const_iterator type_iterator; typedef SmallVectorImpl::const_iterator scope_iterator; diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def new file mode 100644 index 0000000..d5de868 --- /dev/null +++ b/include/llvm/IR/DebugInfoFlags.def @@ -0,0 +1,36 @@ +//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through debug info flags. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#ifndef HANDLE_DI_FLAG +#error "Missing macro definition of HANDLE_DI_FLAG" +#endif + +HANDLE_DI_FLAG(1, Private) +HANDLE_DI_FLAG(2, Protected) +HANDLE_DI_FLAG(3, Public) +HANDLE_DI_FLAG((1 << 2), FwdDecl) +HANDLE_DI_FLAG((1 << 3), AppleBlock) +HANDLE_DI_FLAG((1 << 4), BlockByrefStruct) +HANDLE_DI_FLAG((1 << 5), Virtual) +HANDLE_DI_FLAG((1 << 6), Artificial) +HANDLE_DI_FLAG((1 << 7), Explicit) +HANDLE_DI_FLAG((1 << 8), Prototyped) +HANDLE_DI_FLAG((1 << 9), ObjcClassComplete) +HANDLE_DI_FLAG((1 << 10), ObjectPointer) +HANDLE_DI_FLAG((1 << 11), Vector) +HANDLE_DI_FLAG((1 << 12), StaticMember) +HANDLE_DI_FLAG((1 << 13), LValueReference) +HANDLE_DI_FLAG((1 << 14), RValueReference) + +#undef HANDLE_DI_FLAG diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h new file mode 100644 index 0000000..4534a14 --- /dev/null +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -0,0 +1,1669 @@ +//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations for metadata specific to debug info. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGINFOMETADATA_H +#define LLVM_IR_DEBUGINFOMETADATA_H + +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Dwarf.h" + +// Helper macros for defining get() overrides. +#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ +#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS +#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ + static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ + } \ + static CLASS *getIfExists(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ + /* ShouldCreate */ false); \ + } \ + static CLASS *getDistinct(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ + } \ + static Temp##CLASS getTemporary(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return Temp##CLASS( \ + getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ + } + +namespace llvm { + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class MDLocation : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + MDLocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef MDs); + ~MDLocation() { dropAllReferences(); } + + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + + TempMDLocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) = delete; + +public: + DEFINE_MDNODE_GET(MDLocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + + /// \brief Return a (temporary) clone of this. + TempMDLocation clone() const { return cloneImpl(); } + + unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return SubclassData16; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocationKind; + } +}; + +/// \brief Tagged DWARF-like metadata node. +/// +/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, +/// defined in llvm/Support/Dwarf.h). Called \a DebugNode because it's +/// potentially used for non-DWARF output. +class DebugNode : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + +protected: + DebugNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops1, ArrayRef Ops2 = None) + : MDNode(C, ID, Storage, Ops1, Ops2) { + assert(Tag < 1u << 16); + SubclassData16 = Tag; + } + ~DebugNode() {} + + template Ty *getOperandAs(unsigned I) const { + return cast_or_null(getOperand(I)); + } + + StringRef getStringOperand(unsigned I) const { + if (auto *S = getOperandAs(I)) + return S->getString(); + return StringRef(); + } + + static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { + if (S.empty()) + return nullptr; + return MDString::get(Context, S); + } + +public: + unsigned getTag() const { return SubclassData16; } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case GenericDebugNodeKind: + case MDSubrangeKind: + case MDEnumeratorKind: + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + case MDTemplateTypeParameterKind: + case MDTemplateValueParameterKind: + case MDGlobalVariableKind: + case MDLocalVariableKind: + case MDExpressionKind: + case MDObjCPropertyKind: + case MDImportedEntityKind: + return true; + } + } +}; + +/// \brief Generic tagged DWARF-like metadata node. +/// +/// An un-specialized DWARF-like metadata node. The first operand is a +/// (possibly empty) null-separated \a MDString header that contains arbitrary +/// fields. The remaining operands are \a dwarf_operands(), and are pointers +/// to other metadata. +class GenericDebugNode : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + GenericDebugNode(LLVMContext &C, StorageType Storage, unsigned Hash, + unsigned Tag, ArrayRef Ops1, + ArrayRef Ops2) + : DebugNode(C, GenericDebugNodeKind, Storage, Tag, Ops1, Ops2) { + setHash(Hash); + } + ~GenericDebugNode() { dropAllReferences(); } + + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Header, + ArrayRef DwarfOps, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Header), + DwarfOps, Storage, ShouldCreate); + } + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, + ArrayRef DwarfOps, + StorageType Storage, + bool ShouldCreate = true); + + TempGenericDebugNode cloneImpl() const { + return getTemporary( + getContext(), getTag(), getHeader(), + SmallVector(dwarf_op_begin(), dwarf_op_end())); + } + +public: + unsigned getHash() const { return SubclassData32; } + + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, MDString *Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + + /// \brief Return a (temporary) clone of this. + TempGenericDebugNode clone() const { return cloneImpl(); } + + unsigned getTag() const { return SubclassData16; } + StringRef getHeader() const { return getStringOperand(0); } + + op_iterator dwarf_op_begin() const { return op_begin() + 1; } + op_iterator dwarf_op_end() const { return op_end(); } + op_range dwarf_operands() const { + return op_range(dwarf_op_begin(), dwarf_op_end()); + } + + unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } + const MDOperand &getDwarfOperand(unsigned I) const { + return getOperand(I + 1); + } + void replaceDwarfOperandWith(unsigned I, Metadata *New) { + replaceOperandWith(I + 1, New); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == GenericDebugNodeKind; + } +}; + +/// \brief Array subrange. +/// +/// TODO: Merge into node for DW_TAG_array_type, which should have a custom +/// type. +class MDSubrange : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Count; + int64_t Lo; + + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, + None), + Count(Count), Lo(Lo) {} + ~MDSubrange() {} + + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubrange cloneImpl() const { + return getTemporary(getContext(), getCount(), getLo()); + } + +public: + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + + TempMDSubrange clone() const { return cloneImpl(); } + + int64_t getLo() const { return Lo; } + int64_t getCount() const { return Count; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubrangeKind; + } +}; + +/// \brief Enumeration value. +/// +/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no +/// longer creates a type cycle. +class MDEnumerator : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Value; + + MDEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + ArrayRef Ops) + : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) {} + ~MDEnumerator() {} + + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + StringRef Name, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, + ShouldCreate); + } + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate = true); + + TempMDEnumerator cloneImpl() const { + return getTemporary(getContext(), getValue(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, StringRef Name), + (Value, Name)) + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, MDString *Name), + (Value, Name)) + + TempMDEnumerator clone() const { return cloneImpl(); } + + int64_t getValue() const { return Value; } + StringRef getName() const { return getStringOperand(0); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDEnumeratorKind; + } +}; + +/// \brief Base class for scope-like contexts. +/// +/// Base class for lexical scopes and types (which are also declaration +/// contexts). +/// +/// TODO: Separate the concepts of declaration contexts and lexical scopes. +class MDScope : public DebugNode { +protected: + MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops) {} + ~MDScope() {} + +public: + Metadata *getFile() const { return getOperand(0); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + return true; + } + } +}; + +/// \brief Base class for types. +/// +/// TODO: Remove the hardcoded name and context, since many types don't use +/// them. +/// TODO: Split up flags. +class MDType : public MDScope { + unsigned Line; + unsigned Flags; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + +protected: + MDType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits) {} + ~MDType() {} + +public: + unsigned getLine() const { return Line; } + uint64_t getSizeInBits() const { return SizeInBits; } + uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getOffsetInBits() const { return OffsetInBits; } + unsigned getFlags() const { return Flags; } + + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + return true; + } + } +}; + +/// \brief Basic type. +/// +/// TODO: Split out DW_TAG_unspecified_type. +/// TODO: Drop unused accessors. +class MDBasicType : public MDType { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Encoding; + + MDBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + ArrayRef Ops) + : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + 0, Ops), + Encoding(Encoding) {} + ~MDBasicType() {} + + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + } + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true); + + TempMDBasicType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), + getAlignInBits(), getEncoding()); + } + +public: + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + + TempMDBasicType clone() const { return cloneImpl(); } + + unsigned getEncoding() const { return Encoding; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDBasicTypeKind; + } +}; + +/// \brief Base class for MDDerivedType and MDCompositeType. +/// +/// TODO: Delete; they're not really related. +class MDDerivedTypeBase : public MDType { +protected: + MDDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDDerivedTypeBase() {} + +public: + Metadata *getBaseType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind || + MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Derived types. +/// +/// This includes qualified types, pointers, references, friends, typedefs, and +/// class members. +/// +/// TODO: Split out members (inheritance, fields, methods, etc.). +class MDDerivedType : public MDDerivedTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~MDDerivedType() {} + + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, ExtraData, Storage, ShouldCreate); + } + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true); + + TempMDDerivedType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getExtraData()); + } + +public: + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + + TempMDDerivedType clone() const { return cloneImpl(); } + + /// \brief Get extra data associated with this derived type. + /// + /// Class type for pointer-to-members, objective-c property node for ivars, + /// or global constant wrapper for static members. + /// + /// TODO: Separate out types that need this extra operand: pointer-to-member + /// types and member fields (static members and ivars). + Metadata *getExtraData() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind; + } +}; + +/// \brief Base class for MDCompositeType and MDSubroutineType. +/// +/// TODO: Delete; they're not really related. +class MDCompositeTypeBase : public MDDerivedTypeBase { + unsigned RuntimeLang; + +protected: + MDCompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, unsigned RuntimeLang, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, + OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~MDCompositeTypeBase() {} + +public: + Metadata *getElements() const { return getOperand(4); } + Metadata *getVTableHolder() const { return getOperand(5); } + Metadata *getTemplateParams() const { return getOperand(6); } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + MDString *getRawIdentifier() const { return getOperandAs(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(MDTuple *Elements) { +#ifndef NDEBUG + if (auto *Old = cast_or_null(getElements())) + for (const auto &Op : Old->operands()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); +#endif + replaceOperandWith(4, Elements); + } + void replaceVTableHolder(Metadata *VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(MDTuple *TemplateParams) { + replaceOperandWith(6, TemplateParams); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Composite types. +/// +/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). +/// TODO: Create a custom, unrelated node for DW_TAG_array_type. +class MDCompositeType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDCompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, + RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDCompositeType() {} + + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, + getCanonicalMDString(Context, Identifier), Storage, + ShouldCreate); + } + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + + TempMDCompositeType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier()); + } + +public: + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + StringRef Identifier = ""), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + MDString *Identifier = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + + TempMDCompositeType clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind; + } +}; + +/// \brief Type array for a subprogram. +/// +/// TODO: Detach from CompositeType, and fold the array of types in directly +/// as operands. +class MDSubroutineType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDSubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, + dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, + Ops) {} + ~MDSubroutineType() {} + + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + Metadata *TypeArray, StorageType Storage, + bool ShouldCreate = true); + + TempMDSubroutineType cloneImpl() const { + return getTemporary(getContext(), getFlags(), getTypeArray()); + } + +public: + DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), + (Flags, TypeArray)) + + TempMDSubroutineType clone() const { return cloneImpl(); } + + Metadata *getTypeArray() const { return getElements(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class MDFile : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + MDFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) + : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~MDFile() {} + + static MDFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static MDFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempMDFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempMDFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs(0); } + MDString *getRawDirectory() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDFileKind; + } +}; + +/// \brief Compile unit. +class MDCompileUnit : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned SourceLanguage; + bool IsOptimized; + unsigned RuntimeVersion; + unsigned EmissionKind; + + MDCompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, ArrayRef Ops) + : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} + ~MDCompileUnit() {} + + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, SourceLanguage, File, + getCanonicalMDString(Context, Producer), IsOptimized, + getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), + EmissionKind, EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities, Storage, ShouldCreate); + } + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true); + + TempMDCompileUnit cloneImpl() const { + return getTemporary( + getContext(), getSourceLanguage(), getFile(), getProducer(), + isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), + getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), + getGlobalVariables(), getImportedEntities()); + } + +public: + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + + TempMDCompileUnit clone() const { return cloneImpl(); } + + unsigned getSourceLanguage() const { return SourceLanguage; } + bool isOptimized() const { return IsOptimized; } + unsigned getRuntimeVersion() const { return RuntimeVersion; } + unsigned getEmissionKind() const { return EmissionKind; } + StringRef getProducer() const { return getStringOperand(1); } + StringRef getFlags() const { return getStringOperand(2); } + StringRef getSplitDebugFilename() const { return getStringOperand(3); } + Metadata *getEnumTypes() const { return getOperand(4); } + Metadata *getRetainedTypes() const { return getOperand(5); } + Metadata *getSubprograms() const { return getOperand(6); } + Metadata *getGlobalVariables() const { return getOperand(7); } + Metadata *getImportedEntities() const { return getOperand(8); } + + MDString *getRawProducer() const { return getOperandAs(1); } + MDString *getRawFlags() const { return getOperandAs(2); } + MDString *getRawSplitDebugFilename() const { + return getOperandAs(3); + } + + /// \brief Replace arrays. + /// + /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and + /// deleted on a uniquing collision. In practice, uniquing collisions on \a + /// MDCompileUnit should be fairly rare. + /// @{ + void replaceSubprograms(MDTuple *N) { replaceOperandWith(6, N); } + void replaceGlobalVariables(MDTuple *N) { replaceOperandWith(7, N); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompileUnitKind; + } +}; + +/// \brief Subprogram description. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +/// TODO: Split up flags. +class MDSubprogram : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned ScopeLine; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsLocalToUnit; + bool IsDefinition; + bool IsOptimized; + + MDSubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsLocalToUnit, bool IsDefinition, + bool IsOptimized, ArrayRef Ops) + : MDScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), + Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} + ~MDSubprogram() {} + + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, + StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables, Storage, + ShouldCreate); + } + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubprogram cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getScopeLine(), getContainingType(), + getVirtuality(), getVirtualIndex(), getFlags(), + isOptimized(), getFunction(), getTemplateParams(), + getDeclaration(), getVariables()); + } + +public: + DEFINE_MDNODE_GET( + MDSubprogram, + (Metadata * Scope, StringRef Name, StringRef LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + DEFINE_MDNODE_GET( + MDSubprogram, + (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + + TempMDSubprogram clone() const { return cloneImpl(); } + +public: + unsigned getLine() const { return Line; } + unsigned getVirtuality() const { return Virtuality; } + unsigned getVirtualIndex() const { return VirtualIndex; } + unsigned getScopeLine() const { return ScopeLine; } + unsigned getFlags() const { return Flags; } + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + bool isOptimized() const { return IsOptimized; } + + Metadata *getScope() const { return getOperand(1); } + + StringRef getName() const { return getStringOperand(2); } + StringRef getDisplayName() const { return getStringOperand(3); } + StringRef getLinkageName() const { return getStringOperand(4); } + + MDString *getRawName() const { return getOperandAs(2); } + MDString *getRawLinkageName() const { return getOperandAs(4); } + + Metadata *getType() const { return getOperand(5); } + Metadata *getContainingType() const { return getOperand(6); } + + Metadata *getFunction() const { return getOperand(7); } + Metadata *getTemplateParams() const { return getOperand(8); } + Metadata *getDeclaration() const { return getOperand(9); } + Metadata *getVariables() const { return getOperand(10); } + + /// \brief Replace the function. + /// + /// If \a isUniqued() and not \a isResolved(), this could node will be + /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if + /// that's a problem. + /// @{ + void replaceFunction(Function *F); + void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); } + void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubprogramKind; + } +}; + +class MDLexicalBlockBase : public MDScope { +protected: + MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + ArrayRef Ops) + : MDScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~MDLexicalBlockBase() {} + +public: + Metadata *getScope() const { return getOperand(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind || + MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDLexicalBlock : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Column; + + MDLexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), + Column(Column) {} + ~MDLexicalBlock() {} + + static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, unsigned Column, + StorageType Storage, bool ShouldCreate = true); + + TempMDLexicalBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getLine(), + getColumn()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + + TempMDLexicalBlock clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind; + } +}; + +class MDLexicalBlockFile : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Discriminator; + + MDLexicalBlockFile(LLVMContext &C, StorageType Storage, + unsigned Discriminator, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), + Discriminator(Discriminator) {} + ~MDLexicalBlockFile() {} + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true); + + TempMDLexicalBlockFile cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), + getDiscriminator()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, + (Metadata * Scope, Metadata *File, unsigned Discriminator), + (Scope, File, Discriminator)) + + TempMDLexicalBlockFile clone() const { return cloneImpl(); } + + unsigned getDiscriminator() const { return Discriminator; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDNamespace : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDNamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + ArrayRef Ops) + : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, + Ops), + Line(Line) {} + ~MDNamespace() {} + + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, StringRef Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), + Line, Storage, ShouldCreate); + } + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true); + + TempMDNamespace cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getName(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + StringRef Name, unsigned Line), + (Scope, File, Name, Line)) + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + MDString *Name, unsigned Line), + (Scope, File, Name, Line)) + + TempMDNamespace clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDNamespaceKind; + } +}; + +/// \brief Base class for template parameters. +class MDTemplateParameter : public DebugNode { +protected: + MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : DebugNode(Context, ID, Storage, Tag, Ops) {} + ~MDTemplateParameter() {} + +public: + StringRef getName() const { return getStringOperand(0); } + Metadata *getType() const { return getOperand(1); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind || + MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +class MDTemplateTypeParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateTypeParameter(LLVMContext &Context, StorageType Storage, + ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, Ops) {} + ~MDTemplateTypeParameter() {} + + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, + ShouldCreate); + } + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateTypeParameter cloneImpl() const { + return getTemporary(getContext(), getName(), getType()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + (Name, Type)) + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), + (Name, Type)) + + TempMDTemplateTypeParameter clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind; + } +}; + +class MDTemplateValueParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateValueParameter(LLVMContext &Context, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, + Ops) {} + ~MDTemplateValueParameter() {} + + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, + Value, Storage, ShouldCreate); + } + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateValueParameter cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getType(), + getValue()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + + TempMDTemplateValueParameter clone() const { return cloneImpl(); } + + Metadata *getValue() const { return getOperand(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +/// \brief Base class for variables. +/// +/// TODO: Hardcode to DW_TAG_variable. +class MDVariable : public DebugNode { + unsigned Line; + +protected: + MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~MDVariable() {} + +public: + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + StringRef getName() const { return getStringOperand(1); } + Metadata *getFile() const { return getOperand(2); } + Metadata *getType() const { return getOperand(3); } + + MDString *getRawName() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind || + MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Global variables. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +class MDGlobalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + bool IsLocalToUnit; + bool IsDefinition; + + MDGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + bool IsLocalToUnit, bool IsDefinition, + ArrayRef Ops) + : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + Line, Ops), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + ~MDGlobalVariable() {} + + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, + StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration, Storage, ShouldCreate); + } + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true); + + TempMDGlobalVariable cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getVariable(), + getStaticDataMemberDeclaration()); + } + +public: + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, StringRef Name, StringRef LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, MDString *Name, MDString *LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + + TempMDGlobalVariable clone() const { return cloneImpl(); } + + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + StringRef getDisplayName() const { return getStringOperand(4); } + StringRef getLinkageName() const { return getStringOperand(5); } + Metadata *getVariable() const { return getOperand(6); } + Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); } + + MDString *getRawLinkageName() const { return getOperandAs(5); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Local variable. +/// +/// TODO: Split between arguments and otherwise. +/// TODO: Use \c DW_TAG_variable instead of fake tags. +/// TODO: Split up flags. +class MDLocalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Arg; + unsigned Flags; + + MDLocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned Arg, unsigned Flags, + ArrayRef Ops) + : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + Flags(Flags) {} + ~MDLocalVariable() {} + + static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, StringRef Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), + File, Line, Type, Arg, Flags, InlinedAt, Storage, + ShouldCreate); + } + static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + + TempMDLocalVariable cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getName(), + getFile(), getLine(), getType(), getArg(), getFlags(), + getInlinedAt()); + } + +public: + DEFINE_MDNODE_GET(MDLocalVariable, + (unsigned Tag, Metadata *Scope, StringRef Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt = nullptr), + (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + DEFINE_MDNODE_GET(MDLocalVariable, + (unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt = nullptr), + (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + + TempMDLocalVariable clone() const { return cloneImpl(); } + + unsigned getArg() const { return Arg; } + unsigned getFlags() const { return Flags; } + Metadata *getInlinedAt() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind; + } +}; + +/// \brief DWARF expression. +/// +/// TODO: Co-allocate the expression elements. +/// TODO: Drop fake DW_TAG_expression and separate from DebugNode. +/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary +/// storage types. +class MDExpression : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + std::vector Elements; + + MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) + : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None), + Elements(Elements.begin(), Elements.end()) {} + ~MDExpression() {} + + static MDExpression *getImpl(LLVMContext &Context, + ArrayRef Elements, StorageType Storage, + bool ShouldCreate = true); + + TempMDExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(MDExpression, (ArrayRef Elements), (Elements)) + + TempMDExpression clone() const { return cloneImpl(); } + + ArrayRef getElements() const { return Elements; } + + unsigned getNumElements() const { return Elements.size(); } + uint64_t getElement(unsigned I) const { + assert(I < Elements.size() && "Index out of range"); + return Elements[I]; + } + + typedef ArrayRef::iterator element_iterator; + element_iterator elements_begin() const { return getElements().begin(); } + element_iterator elements_end() const { return getElements().end(); } + + /// \brief A lightweight wrapper around an expression operand. + /// + /// TODO: Store arguments directly and change \a MDExpression to store a + /// range of these. + class ExprOperand { + const uint64_t *Op; + + public: + explicit ExprOperand(const uint64_t *Op) : Op(Op) {} + + const uint64_t *get() const { return Op; } + + /// \brief Get the operand code. + uint64_t getOp() const { return *Op; } + + /// \brief Get an argument to the operand. + /// + /// Never returns the operand itself. + uint64_t getArg(unsigned I) const { return Op[I + 1]; } + + unsigned getNumArgs() const { return getSize() - 1; } + + /// \brief Return the size of the operand. + /// + /// Return the number of elements in the operand (1 + args). + unsigned getSize() const; + }; + + /// \brief An iterator for expression operands. + class expr_op_iterator + : public std::iterator { + ExprOperand Op; + + public: + explicit expr_op_iterator(element_iterator I) : Op(I) {} + + element_iterator getBase() const { return Op.get(); } + const ExprOperand &operator*() const { return Op; } + const ExprOperand *operator->() const { return &Op; } + + expr_op_iterator &operator++() { + increment(); + return *this; + } + expr_op_iterator operator++(int) { + expr_op_iterator T(*this); + increment(); + return T; + } + + bool operator==(const expr_op_iterator &X) const { + return getBase() == X.getBase(); + } + bool operator!=(const expr_op_iterator &X) const { + return getBase() != X.getBase(); + } + + private: + void increment() { Op = ExprOperand(getBase() + Op.getSize()); } + }; + + /// \brief Visit the elements via ExprOperand wrappers. + /// + /// These range iterators visit elements through \a ExprOperand wrappers. + /// This is not guaranteed to be a valid range unless \a isValid() gives \c + /// true. + /// + /// \pre \a isValid() gives \c true. + /// @{ + expr_op_iterator expr_op_begin() const { + return expr_op_iterator(elements_begin()); + } + expr_op_iterator expr_op_end() const { + return expr_op_iterator(elements_end()); + } + /// @} + + bool isValid() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDExpressionKind; + } +}; + +class MDObjCProperty : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Attributes; + + MDObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Attributes, ArrayRef Ops) + : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), + Line(Line), Attributes(Attributes) {} + ~MDObjCProperty() {} + + static MDObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, + getCanonicalMDString(Context, GetterName), + getCanonicalMDString(Context, SetterName), Attributes, Type, + Storage, ShouldCreate); + } + static MDObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type, + StorageType Storage, bool ShouldCreate = true); + + TempMDObjCProperty cloneImpl() const { + return getTemporary(getContext(), getName(), getFile(), getLine(), + getGetterName(), getSetterName(), getAttributes(), + getType()); + } + +public: + DEFINE_MDNODE_GET(MDObjCProperty, + (StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + DEFINE_MDNODE_GET(MDObjCProperty, + (MDString * Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + + TempMDObjCProperty clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getAttributes() const { return Attributes; } + StringRef getName() const { return getStringOperand(0); } + Metadata *getFile() const { return getOperand(1); } + StringRef getGetterName() const { return getStringOperand(2); } + StringRef getSetterName() const { return getStringOperand(3); } + Metadata *getType() const { return getOperand(4); } + + MDString *getRawName() const { return getOperandAs(0); } + MDString *getRawGetterName() const { return getOperandAs(2); } + MDString *getRawSetterName() const { return getOperandAs(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDObjCPropertyKind; + } +}; + +class MDImportedEntity : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~MDImportedEntity() {} + + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, Entity, Line, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); + } + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate = true); + + TempMDImportedEntity cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getEntity(), + getLine(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, Line, Name)) + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name), + (Tag, Scope, Entity, Line, Name)) + + TempMDImportedEntity clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getEntity() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDImportedEntityKind; + } +}; + +} // end namespace llvm + +#undef DEFINE_MDNODE_GET_UNPACK_IMPL +#undef DEFINE_MDNODE_GET_UNPACK +#undef DEFINE_MDNODE_GET + +#endif diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 3d969a8..86e6441 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -15,51 +15,41 @@ #ifndef LLVM_IR_DEBUGLOC_H #define LLVM_IR_DEBUGLOC_H +#include "llvm/IR/TrackingMDRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { - template struct DenseMapInfo; - class MDNode; + class LLVMContext; class raw_ostream; + class MDNode; /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an /// operation. class DebugLoc { - friend struct DenseMapInfo; - - /// getEmptyKey() - A private constructor that returns an unknown that is - /// not equal to the tombstone key or DebugLoc(). - static DebugLoc getEmptyKey() { - DebugLoc DL; - DL.LineCol = 1; - return DL; - } + TrackingMDNodeRef Loc; - /// getTombstoneKey() - A private constructor that returns an unknown that - /// is not equal to the empty key or DebugLoc(). - static DebugLoc getTombstoneKey() { - DebugLoc DL; - DL.LineCol = 2; - return DL; + public: + DebugLoc() {} + DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {} + DebugLoc(const DebugLoc &X) : Loc(X.Loc) {} + DebugLoc &operator=(DebugLoc &&X) { + Loc = std::move(X.Loc); + return *this; + } + DebugLoc &operator=(const DebugLoc &X) { + Loc = X.Loc; + return *this; } - /// LineCol - This 32-bit value encodes the line and column number for the - /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 - /// for either means unknown. - uint32_t LineCol; - - /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, - /// decoded by LLVMContext. 0 is unknown. - int ScopeIdx; - public: - DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = nullptr); + static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, + MDNode *InlinedAt = nullptr); /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -68,56 +58,54 @@ namespace llvm { static DebugLoc getFromDILexicalBlock(MDNode *N); /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return ScopeIdx == 0; } + bool isUnknown() const { return !Loc; } - unsigned getLine() const { - return (LineCol << 8) >> 8; // Mask out column. - } - - unsigned getCol() const { - return LineCol >> 24; - } + unsigned getLine() const; + unsigned getCol() const; /// getScope - This returns the scope pointer for this DebugLoc, or null if /// invalid. - MDNode *getScope(const LLVMContext &Ctx) const; + MDNode *getScope() const; + MDNode *getScope(const LLVMContext &) const { return getScope(); } /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or /// null if invalid or not present. - MDNode *getInlinedAt(const LLVMContext &Ctx) const; + MDNode *getInlinedAt() const; + MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const; + const LLVMContext &) const { + return getScopeAndInlinedAt(Scope, IA); + } /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode(const LLVMContext &Ctx) const; + MDNode *getScopeNode() const; + MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } // getFnDebugLoc - Walk up the scope chain of given debug loc and find line // number info for the function. - DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; + DebugLoc getFnDebugLoc() const; + DebugLoc getFnDebugLoc(const LLVMContext &) const { + return getFnDebugLoc(); + } /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. - MDNode *getAsMDNode(const LLVMContext &Ctx) const; + MDNode *getAsMDNode() const; + MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } - bool operator==(const DebugLoc &DL) const { - return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; - } + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - void dump(const LLVMContext &Ctx) const; + void dump() const; + void dump(const LLVMContext &) const { dump(); } /// \brief prints source location /path/to/file.exe:line:col @[inlined at] - void print(const LLVMContext &Ctx, raw_ostream &OS) const; + void print(raw_ostream &OS) const; + void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; - template <> - struct DenseMapInfo { - static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } - static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } - static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } - }; } // end namespace llvm #endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 534d1e5..76f8064 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -94,8 +94,8 @@ public: /// FunctionType - Class to represent function types /// class FunctionType : public Type { - FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; - const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; + FunctionType(const FunctionType &) = delete; + const FunctionType &operator=(const FunctionType &) = delete; FunctionType(Type *Result, ArrayRef Params, bool IsVarArgs); public: @@ -123,6 +123,9 @@ public: typedef Type::subtype_iterator param_iterator; param_iterator param_begin() const { return ContainedTys + 1; } param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + ArrayRef params() const { + return makeArrayRef(param_begin(), param_end()); + } /// Parameter type accessors. Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } @@ -185,8 +188,8 @@ public: /// generator for a target expects). /// class StructType : public CompositeType { - StructType(const StructType &) LLVM_DELETED_FUNCTION; - const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; + StructType(const StructType &) = delete; + const StructType &operator=(const StructType &) = delete; StructType(LLVMContext &C) : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} enum { @@ -274,6 +277,9 @@ public: typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef const elements() const { + return makeArrayRef(element_begin(), element_end()); + } /// isLayoutIdentical - Return true if this is layout identical to the /// specified struct. @@ -302,8 +308,8 @@ public: /// class SequentialType : public CompositeType { Type *ContainedType; ///< Storage for the single contained type. - SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; - const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; + SequentialType(const SequentialType &) = delete; + const SequentialType &operator=(const SequentialType &) = delete; protected: SequentialType(TypeID TID, Type *ElType) @@ -329,8 +335,8 @@ public: class ArrayType : public SequentialType { uint64_t NumElements; - ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; - const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; + ArrayType(const ArrayType &) = delete; + const ArrayType &operator=(const ArrayType &) = delete; ArrayType(Type *ElType, uint64_t NumEl); public: /// ArrayType::get - This static method is the primary way to construct an @@ -355,8 +361,8 @@ public: class VectorType : public SequentialType { unsigned NumElements; - VectorType(const VectorType &) LLVM_DELETED_FUNCTION; - const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; + VectorType(const VectorType &) = delete; + const VectorType &operator=(const VectorType &) = delete; VectorType(Type *ElType, unsigned NumEl); public: /// VectorType::get - This static method is the primary way to construct an @@ -440,8 +446,8 @@ public: /// PointerType - Class to represent pointers. /// class PointerType : public SequentialType { - PointerType(const PointerType &) LLVM_DELETED_FUNCTION; - const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; + PointerType(const PointerType &) = delete; + const PointerType &operator=(const PointerType &) = delete; explicit PointerType(Type *ElType, unsigned AddrSpace); public: /// PointerType::get - This constructs a pointer to an object of the specified diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index b592f89..c6a8854 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -45,6 +45,7 @@ enum DiagnosticSeverity { /// \brief Defines the different supported kind of a diagnostic. /// This enum should be extended with a new ID for each added concrete subclass. enum DiagnosticKind { + DK_Bitcode, DK_InlineAsm, DK_StackSize, DK_Linker, @@ -97,6 +98,8 @@ public: virtual void print(DiagnosticPrinter &DP) const = 0; }; +typedef std::function DiagnosticHandlerFunction; + /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. class DiagnosticInfoInlineAsm : public DiagnosticInfo { diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index e2d1ccc..c1f208e 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -31,6 +31,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); @@ -69,6 +74,13 @@ public: DominatorTree() : DominatorTreeBase(false) {} + DominatorTree(DominatorTree &&Arg) + : Base(std::move(static_cast(Arg))) {} + DominatorTree &operator=(DominatorTree &&RHS) { + Base::operator=(std::move(static_cast(RHS))); + return *this; + } + /// \brief Returns *false* if the other dominator tree matches this dominator /// tree. inline bool compare(const DominatorTree &Other) const { @@ -155,6 +167,43 @@ template <> struct GraphTraits }; /// \brief Analysis pass which computes a \c DominatorTree. +class DominatorTreeAnalysis { +public: + /// \brief Provide the result typedef for this analysis pass. + typedef DominatorTree Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Run the analysis pass over a function and produce a dominator tree. + DominatorTree run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "DominatorTreeAnalysis"; } + +private: + static char PassID; +}; + +/// \brief Printer pass for the \c DominatorTree. +class DominatorTreePrinterPass { + raw_ostream &OS; + +public: + explicit DominatorTreePrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreePrinterPass"; } +}; + +/// \brief Verifier pass for the \c DominatorTree. +struct DominatorTreeVerifierPass { + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreeVerifierPass"; } +}; + +/// \brief Legacy analysis pass which computes a \c DominatorTree. class DominatorTreeWrapperPass : public FunctionPass { DominatorTree DT; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 26d893b..0cd5afb 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -87,11 +87,14 @@ private: ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3-6: CallingConvention + */ friend class SymbolTableListTraits; @@ -102,7 +105,7 @@ private: /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -110,8 +113,8 @@ private: } void BuildLazyArguments() const; - Function(const Function&) LLVM_DELETED_FUNCTION; - void operator=(const Function&) LLVM_DELETED_FUNCTION; + Function(const Function&) = delete; + void operator=(const Function&) = delete; /// Do the actual lookup of an intrinsic ID when the query could not be /// answered from the cache. @@ -162,11 +165,11 @@ public: /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. CallingConv::ID getCallingConv() const { - return static_cast(getSubclassDataFromValue() >> 2); + return static_cast(getSubclassDataFromValue() >> 3); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 3) | - (static_cast(CC) << 2)); + setValueSubclassData((getSubclassDataFromValue() & 7) | + (static_cast(CC) << 3)); } /// @brief Return the attribute list for this Function. @@ -215,6 +218,11 @@ public: return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); } + /// \brief Return the stack alignment for the function. + unsigned getFnStackAlignment() const { + return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -231,6 +239,9 @@ public: /// @brief removes the attributes from the list of attributes. void removeAttributes(unsigned i, AttributeSet attr); + /// @brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeSets.getParamAlignment(i); @@ -448,12 +459,19 @@ public: bool arg_empty() const; bool hasPrefixData() const { - return getSubclassDataFromValue() & 2; + return getSubclassDataFromValue() & (1<<1); } Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index a7d68ec..6f57dc2 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -19,11 +19,13 @@ #define LLVM_IR_GVMATERIALIZER_H #include +#include namespace llvm { class Function; class GlobalValue; class Module; +class StructType; class GVMaterializer { protected: @@ -50,6 +52,8 @@ public: /// Make sure the entire Module has been completely read. /// virtual std::error_code MaterializeModule(Module *M) = 0; + + virtual std::vector getIdentifiedStructTypes() const = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 075b570..d0672c8 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -28,8 +28,8 @@ template class GlobalAlias : public GlobalValue, public ilist_node { friend class SymbolTableListTraits; - void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; - GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; + void operator=(const GlobalAlias &) = delete; + GlobalAlias(const GlobalAlias &) = delete; void setParent(Module *parent); diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 546fea2..50deb08 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -24,7 +24,7 @@ class Comdat; class Module; class GlobalObject : public GlobalValue { - GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION; + GlobalObject(const GlobalObject &) = delete; protected: GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index e7b5d58..aaecc1d 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -20,7 +20,6 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" - #include namespace llvm { @@ -30,7 +29,7 @@ class PointerType; class Module; class GlobalValue : public Constant { - GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; + GlobalValue(const GlobalValue &) = delete; public: /// @brief An enumeration for the kinds of linkage for global values. enum LinkageTypes { diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 4189ccb..d7b81a2 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -34,9 +34,9 @@ template class GlobalVariable : public GlobalObject, public ilist_node { friend class SymbolTableListTraits; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; - GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void operator=(const GlobalVariable &) = delete; + GlobalVariable(const GlobalVariable &) = delete; void setParent(Module *parent); diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 088c7b4..33649d7 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -115,12 +115,10 @@ public: } /// \brief Set location information used by debugging information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } + void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } /// \brief Get location information used by debugging information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } /// \brief If this builder has a current debug location, set it on the /// specified instruction. @@ -200,8 +198,8 @@ public: BasicBlock::iterator Point; DebugLoc DbgLoc; - InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; - InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard(const InsertPointGuard &) = delete; + InsertPointGuard &operator=(const InsertPointGuard &) = delete; public: InsertPointGuard(IRBuilderBase &B) @@ -221,9 +219,9 @@ public: FastMathFlags FMF; MDNode *FPMathTag; - FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard(const FastMathFlagGuard &) = delete; FastMathFlagGuard &operator=( - const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + const FastMathFlagGuard &) = delete; public: FastMathFlagGuard(IRBuilderBase &B) @@ -429,11 +427,54 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + /// \brief Create a call to Masked Load intrinsic + CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, + Value *PassThru = 0, const Twine &Name = ""); + + /// \brief Create a call to Masked Store intrinsic + CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, + Value *Mask); + /// \brief Create an assume intrinsic call that allows the optimizer to /// assume that the provided condition will be true. CallInst *CreateAssumption(Value *Cond); + /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepoint(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + // Conveninence function for the common case when CallArgs are filled in using + // makeArrayRef(CS.arg_begin(), .arg_end()); Use needs to be .get()'ed to get + // the Value *. + CallInst *CreateGCStatepoint(Value *ActualCallee, ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// the result from a call wrapped in a statepoint. + CallInst *CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// project the relocated value of one pointer from the statepoint. + CallInst *CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name = ""); + private: + /// \brief Create a call to a masked intrinsic with given Id. + /// Masked intrinsic has only one overloaded type - data type. + CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef Ops, + Type *DataTy, const Twine &Name = ""); + Value *getCastedInt8PtrValue(Value *Ptr); }; @@ -1246,11 +1287,23 @@ public: return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } + + Value *CreateBitOrPointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (V->getType()->isPointerTy() && DestTy->isIntegerTy()) + return CreatePtrToInt(V, DestTy, Name); + if (V->getType()->isIntegerTy() && DestTy->isPointerTy()) + return CreateIntToPtr(V, DestTy, Name); + + return CreateBitCast(V, DestTy, Name); + } private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; + Value *CreateIntCast(Value *, Type *, const char *) = delete; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index afea0c3..7f2027b 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -58,7 +58,7 @@ public: PrintModulePass(); PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "PrintModulePass"; } }; @@ -75,7 +75,7 @@ public: PrintFunctionPass(); PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Function &F); static StringRef name() { return "PrintFunctionPass"; } }; diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index b2d79d0..84ae9df 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -40,8 +40,8 @@ private: friend struct InlineAsmKeyType; friend class ConstantUniqueMap; - InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; - void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; + InlineAsm(const InlineAsm &) = delete; + void operator=(const InlineAsm&) = delete; std::string AsmString, Constraints; bool HasSideEffects; diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 75e93bd..0bb2854 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -127,20 +127,32 @@ typedef InstIterator, inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline iterator_range inst_range(Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function *F) { return const_inst_iterator(*F); } inline const_inst_iterator inst_end(const Function *F) { return const_inst_iterator(*F, true); } +inline iterator_range inst_range(const Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline iterator_range inst_range(Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function &F) { return const_inst_iterator(F); } inline const_inst_iterator inst_end(const Function &F) { return const_inst_iterator(F, true); } +inline iterator_range inst_range(const Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} } // End llvm namespace diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 186fc88..e086282 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -83,7 +83,7 @@ public: //===----------------------------------------------------------------------===// class UnaryInstruction : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, @@ -132,7 +132,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// class BinaryOperator : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: void init(BinaryOps iType); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, @@ -489,6 +489,19 @@ public: Instruction *InsertBefore = 0 ///< Place to insert the instruction ); + /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. + /// + /// If the value is a pointer type and the destination an integer type, + /// creates a PtrToInt cast. If the value is an integer type and the + /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates + /// a bitcast. + static CastInst *CreateBitOrPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) @@ -551,6 +564,17 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these + /// types is valid and a no-op. + /// + /// This ensures that any pointer<->integer cast has enough bits in the + /// integer and any other cast is a bitcast. + static bool isBitOrNoopPointerCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout *Layout = 0 ///< Optional DataLayout. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type @@ -650,8 +674,8 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. class CmpInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - CmpInst() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + CmpInst() = delete; protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index ba7791c..dfece3e 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -31,8 +31,8 @@ template class SymbolTableListTraits; class Instruction : public User, public ilist_node { - void operator=(const Instruction &) LLVM_DELETED_FUNCTION; - Instruction(const Instruction &) LLVM_DELETED_FUNCTION; + void operator=(const Instruction &) = delete; + Instruction(const Instruction &) = delete; BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. @@ -201,7 +201,7 @@ public: void setAAMetadata(const AAMDNodes &N); /// setDebugLoc - Set the debug location information for this instruction. - void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } /// getDebugLoc - Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index dcf19e0..83f9d04 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -17,8 +17,8 @@ #define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" @@ -285,7 +285,7 @@ private: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void AssertOK(); protected: StoreInst *clone_impl() const override; @@ -411,7 +411,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) /// FenceInst - an instruction for ordering other memory operations /// class FenceInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: FenceInst *clone_impl() const override; @@ -478,7 +478,7 @@ private: /// there. Returns the value that was loaded. /// class AtomicCmpXchgInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); @@ -634,7 +634,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// the old value. /// class AtomicRMWInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: AtomicRMWInst *clone_impl() const override; public: @@ -845,6 +845,13 @@ public: return cast(Instruction::getType()); } + Type *getSourceElementType() const { + SequentialType *Ty = cast(getPointerOperandType()); + if (VectorType *VTy = dyn_cast(Ty)) + Ty = cast(VTy->getElementType()); + return Ty->getElementType(); + } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space @@ -1375,6 +1382,9 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -1958,7 +1968,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg, class InsertValueInst : public Instruction { SmallVector Indices; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; InsertValueInst(const InsertValueInst &IVI); void init(Value *Agg, Value *Val, ArrayRef Idxs, const Twine &NameStr); @@ -2088,7 +2098,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. unsigned ReservedSpace; @@ -2163,6 +2173,8 @@ public: return block_begin() + getNumOperands(); } + op_range incoming_values() { return operands(); } + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands(); } @@ -2295,7 +2307,7 @@ class LandingPadInst : public Instruction { public: enum ClauseType { Catch, Filter }; private: - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; // Allocate space for exactly zero operands. void *operator new(size_t s) { return User::operator new(s, 0); @@ -2562,7 +2574,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2871,7 +2883,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) /// IndirectBrInst - Indirect Branch Instruction. /// class IndirectBrInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -3056,6 +3068,9 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief removes the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -3296,7 +3311,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) /// end of the block cannot be reached. /// class UnreachableInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnreachableInst *clone_impl() const override; diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index e3d7999..d434432 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -28,15 +28,16 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Metadata.h" namespace llvm { /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic /// functions. This allows the standard isa/dyncast/cast functionality to /// work with calls to intrinsic functions. class IntrinsicInst : public CallInst { - IntrinsicInst() LLVM_DELETED_FUNCTION; - IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; - void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + IntrinsicInst() = delete; + IntrinsicInst(const IntrinsicInst&) = delete; + void operator=(const IntrinsicInst&) = delete; public: /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// @@ -81,8 +82,14 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { return cast(getArgOperand(1)); } - MDNode *getExpression() const { return cast(getArgOperand(2)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(1))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -103,8 +110,14 @@ namespace llvm { return cast( const_cast(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { return cast(getArgOperand(2)); } - MDNode *getExpression() const { return cast(getArgOperand(3)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(3))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -322,6 +335,33 @@ namespace llvm { Value *getSrc() const { return const_cast(getArgOperand(1)); } }; + /// This represents the llvm.instrprof_increment intrinsic. + class InstrProfIncrementInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::instrprof_increment; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + GlobalVariable *getName() const { + return cast( + const_cast(getArgOperand(0))->stripPointerCasts()); + } + + ConstantInt *getHash() const { + return cast(const_cast(getArgOperand(1))); + } + + ConstantInt *getNumCounters() const { + return cast(const_cast(getArgOperand(2))); + } + + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(3))); + } + }; } #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index acc0e9e..a66bd2c 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -41,7 +41,7 @@ namespace Intrinsic { #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; - + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef Tys = None); @@ -69,16 +69,17 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - + /// This is a type descriptor which explains the type requirements of an /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendArgument, TruncArgument, HalfVecArgument + Argument, ExtendArgument, TruncArgument, HalfVecArgument, + SameVecWidthArgument, PtrToArgument, VecOfPtrsToElt } Kind; - + union { unsigned Integer_Width; unsigned Float_Width; @@ -87,8 +88,9 @@ namespace Intrinsic { unsigned Struct_NumElements; unsigned Argument_Info; }; - + enum ArgKind { + AK_Any, AK_AnyInteger, AK_AnyFloat, AK_AnyVector, @@ -96,25 +98,29 @@ namespace Intrinsic { }; unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return Argument_Info >> 2; + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return (ArgKind)(Argument_Info&3); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return (ArgKind)(Argument_Info & 7); } - + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { IITDescriptor Result = { K, { Field } }; return Result; } }; - + /// Return the IIT table descriptor for the specified intrinsic into an array /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T); - + } // End Intrinsic namespace } // End llvm namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 98d48de..e89e65d 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -112,12 +112,19 @@ class LLVMMatchType // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType : LLVMMatchType; class LLVMTruncatedType : LLVMMatchType; +class LLVMVectorSameWidth + : LLVMMatchType { + ValueType ElTy = elty.VT; +} +class LLVMPointerTo : LLVMMatchType; +class LLVMVectorOfPointersToElt : LLVMMatchType; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many class LLVMHalfElementsVectorType : LLVMMatchType; def llvm_void_ty : LLVMType; +def llvm_any_ty : LLVMType; def llvm_anyint_ty : LLVMType; def llvm_anyfloat_ty : LLVMType; def llvm_anyvector_ty : LLVMType; @@ -254,6 +261,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_framerecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], @@ -287,6 +298,12 @@ def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], [IntrReadWriteArgMem]>; +// A counter increment for instrumentation based profiling. +def int_instrprof_increment : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + []>; + //===------------------- Standard C Library Intrinsics --------------------===// // @@ -394,6 +411,11 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; +// eh.begincatch takes a pointer returned by a landingpad instruction and +// returns the exception object pointer for the exception to be handled. +def int_eh_begincatch : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; +def int_eh_endcatch : Intrinsic<[], []>; + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. @@ -493,6 +515,24 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], llvm_vararg_ty], [Throws]>; + +//===------------------------ Garbage Collection Intrinsics ---------------===// +// These are documented in docs/Statepoint.rst + +def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_vararg_ty]>; + +def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>; +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; + +// Deprecated: will be removed in a couple of weeks +def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], + [llvm_i32_ty]>; +def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; + //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -539,6 +579,34 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; +//===-------------------------- Masked Intrinsics -------------------------===// +// +def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>, + llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +def int_masked_load : Intrinsic<[llvm_anyvector_ty], + [LLVMPointerTo<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_gather: Intrinsic<[llvm_anyvector_ty], + [LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_scatter: Intrinsic<[], + [llvm_anyvector_ty, + LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +// Intrinsics to support bit sets. +def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], + [IntrNoMem]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// @@ -552,3 +620,4 @@ include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" +include "llvm/IR/IntrinsicsBPF.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td new file mode 100644 index 0000000..6b5110b --- /dev/null +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -0,0 +1,22 @@ +//===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the BPF-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +// Specialized loads from packet +let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." + def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; +} diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8a88729..b566956 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -254,7 +254,7 @@ class Hexagon_qi_qiqi_Intrinsic // class Hexagon_qi_qiqiqi_Intrinsic : Hexagon_Intrinsic; // // DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> @@ -434,7 +434,7 @@ class Hexagon_mem_memmemsisi_Intrinsic class Hexagon_sf_si_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_sf_df_Intrinsic // @@ -490,21 +490,21 @@ class Hexagon_si_df_Intrinsic class Hexagon_sf_sfsf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsf_Intrinsic +// Hexagon_si_sfsf_Intrinsic // -class Hexagon_qi_sfsf_Intrinsic +class Hexagon_si_sfsf_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsi_Intrinsic +// Hexagon_si_sfsi_Intrinsic // -class Hexagon_qi_sfsi_Intrinsic +class Hexagon_si_sfsi_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // Hexagon_qi_sfqi_Intrinsic // @@ -519,7 +519,7 @@ class Hexagon_sf_sfsfsf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_sf_sfsfsfqi_Intrinsic // @@ -528,7 +528,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_di_dididi_Intrinsic // @@ -543,7 +543,7 @@ class Hexagon_di_dididisi_Intrinsic class Hexagon_df_si_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_df_di_Intrinsic // @@ -571,21 +571,21 @@ class Hexagon_df_df_Intrinsic class Hexagon_df_dfdf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfdf_Intrinsic +// Hexagon_si_dfdf_Intrinsic // -class Hexagon_qi_dfdf_Intrinsic +class Hexagon_si_dfdf_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfsi_Intrinsic +// Hexagon_si_dfsi_Intrinsic // -class Hexagon_qi_dfsi_Intrinsic +class Hexagon_si_dfsi_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // // Hexagon_df_dfdfdf_Intrinsic @@ -594,7 +594,7 @@ class Hexagon_df_dfdfdf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_df_dfdfdf_Intrinsic // @@ -603,7 +603,7 @@ class Hexagon_df_dfdfdfqi_Intrinsic [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // This one below will not be generated from iset.py. @@ -624,32 +624,32 @@ Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; // BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; // // BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpeqp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtup : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; // // BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) // @@ -674,182 +674,182 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">; // BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) // def int_hexagon_C2_bitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsset">; // // BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; // // BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; // // BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; // // BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; // // BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgeui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; // // BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) // def int_hexagon_C2_cmplt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmplt">; // // BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpltu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; // // BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; // // BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; // // BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) // def int_hexagon_C4_cmpltei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; // // BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; // // BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; // // BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) // def int_hexagon_C4_cmplte : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplte">; // // BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; // // BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) // def int_hexagon_C2_and : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_and">; // // BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) // def int_hexagon_C2_or : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_or">; // // BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) // def int_hexagon_C2_xor : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_xor">; // // BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) // def int_hexagon_C2_andn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_andn">; // // BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) // def int_hexagon_C2_not : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_not">; // // BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) // def int_hexagon_C2_orn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_orn">; // // BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_and">; // // BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_or">; // // BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_and">; // // BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_or">; // // BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_andn">; // // BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_orn">; // // BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_andn">; // // BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_orn">; // // BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) // def int_hexagon_C2_pxfer_map : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; // // BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) // def int_hexagon_C2_any8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_any8">; // // BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) // def int_hexagon_C2_all8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_all8">; // // BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) // @@ -889,167 +889,167 @@ Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">; // BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbeq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbeqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbeq_any : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; // // BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; // // BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpheq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpheqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; // // BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; // // BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpweq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpweqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; // // BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2) // def int_hexagon_A4_boundscheck : -Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; +Hexagon_si_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; // // BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2) // def int_hexagon_A4_tlbmatch : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; // // BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) // @@ -1059,17 +1059,17 @@ Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">; // BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) // def int_hexagon_C2_tfrrp : -Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_tfrrp">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9 : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9_not : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; // // BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) // @@ -2849,7 +2849,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">; // BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) // def int_hexagon_A2_tfrpi : -Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">; +Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">; // // BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) // @@ -3609,22 +3609,22 @@ Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">; // BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpeq : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpgt : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpge : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpuo : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2) // @@ -3639,7 +3639,7 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">; // BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2) // def int_hexagon_F2_sfclass : -Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; +Hexagon_si_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; // // BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1) // @@ -3666,80 +3666,30 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">; def int_hexagon_F2_sffixupr : Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">; // -// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfadd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">; -// -// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfsub : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmpy : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4) -// -def int_hexagon_F2_dffma_sc : -Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmax : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmin : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">; -// // BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpeq : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpgt : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpge : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpuo : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2) // def int_hexagon_F2_dfclass : -Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; +Hexagon_si_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; // // BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1) // @@ -3751,21 +3701,6 @@ Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">; def int_hexagon_F2_dfimm_n : Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">; // -// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupn : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1) -// -def int_hexagon_F2_dffixupr : -Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">; -// // BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1) // def int_hexagon_F2_conv_sf2df : @@ -4494,12 +4429,12 @@ Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">; // BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; // // BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) // @@ -4519,12 +4454,12 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">; // BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; // // BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) // @@ -4875,3 +4810,21 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // def int_hexagon_S2_deinterleave : Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; + +def llvm_ptr32_ty : LLVMPointerType; +def llvm_ptr64_ty : LLVMPointerType; + +// Mark locked loads as read/write to prevent any accidental reordering. +def int_hexagon_L2_loadw_locked : +Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_L4_loadd_locked : +Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +def int_hexagon_S2_storew_locked : +Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty], + [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_S4_stored_locked : +Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty], + [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 5cdabde..110d55d 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -542,3 +542,180 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; } + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsics. +// + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_QPX_Intrinsic - Base class for all QPX intrinsics. + class PowerPC_QPX_Intrinsic ret_types, + list param_types, + list properties> + : GCCBuiltin, + Intrinsic; +} + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Class Definitions. +// + +/// PowerPC_QPX_FF_Intrinsic - A PowerPC intrinsic that takes one v4f64 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_FFFF_Intrinsic - A PowerPC intrinsic that takes three v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFFF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64. +class PowerPC_QPX_Load_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64 permutation. +class PowerPC_QPX_LoadPerm_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and stores a v4f64. +class PowerPC_QPX_Store_Intrinsic + : PowerPC_QPX_Intrinsic; + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Add Instructions + def int_ppc_qpx_qvfadd : PowerPC_QPX_FFF_Intrinsic<"qvfadd">; + def int_ppc_qpx_qvfadds : PowerPC_QPX_FFF_Intrinsic<"qvfadds">; + def int_ppc_qpx_qvfsub : PowerPC_QPX_FFF_Intrinsic<"qvfsub">; + def int_ppc_qpx_qvfsubs : PowerPC_QPX_FFF_Intrinsic<"qvfsubs">; + + // Estimate Instructions + def int_ppc_qpx_qvfre : PowerPC_QPX_FF_Intrinsic<"qvfre">; + def int_ppc_qpx_qvfres : PowerPC_QPX_FF_Intrinsic<"qvfres">; + def int_ppc_qpx_qvfrsqrte : PowerPC_QPX_FF_Intrinsic<"qvfrsqrte">; + def int_ppc_qpx_qvfrsqrtes : PowerPC_QPX_FF_Intrinsic<"qvfrsqrtes">; + + // Multiply Instructions + def int_ppc_qpx_qvfmul : PowerPC_QPX_FFF_Intrinsic<"qvfmul">; + def int_ppc_qpx_qvfmuls : PowerPC_QPX_FFF_Intrinsic<"qvfmuls">; + def int_ppc_qpx_qvfxmul : PowerPC_QPX_FFF_Intrinsic<"qvfxmul">; + def int_ppc_qpx_qvfxmuls : PowerPC_QPX_FFF_Intrinsic<"qvfxmuls">; + + // Multiply-add instructions + def int_ppc_qpx_qvfmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfmadd">; + def int_ppc_qpx_qvfmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfmadds">; + def int_ppc_qpx_qvfnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadd">; + def int_ppc_qpx_qvfnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadds">; + def int_ppc_qpx_qvfmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfmsub">; + def int_ppc_qpx_qvfmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfmsubs">; + def int_ppc_qpx_qvfnmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsub">; + def int_ppc_qpx_qvfnmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsubs">; + def int_ppc_qpx_qvfxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadd">; + def int_ppc_qpx_qvfxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadds">; + def int_ppc_qpx_qvfxxnpmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadd">; + def int_ppc_qpx_qvfxxnpmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadds">; + def int_ppc_qpx_qvfxxcpnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadd">; + def int_ppc_qpx_qvfxxcpnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadds">; + def int_ppc_qpx_qvfxxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadd">; + def int_ppc_qpx_qvfxxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadds">; + + // Select Instruction + def int_ppc_qpx_qvfsel : PowerPC_QPX_FFFF_Intrinsic<"qvfsel">; + + // Permute Instruction + def int_ppc_qpx_qvfperm : PowerPC_QPX_FFFF_Intrinsic<"qvfperm">; + + // Convert and Round Instructions + def int_ppc_qpx_qvfctid : PowerPC_QPX_FF_Intrinsic<"qvfctid">; + def int_ppc_qpx_qvfctidu : PowerPC_QPX_FF_Intrinsic<"qvfctidu">; + def int_ppc_qpx_qvfctidz : PowerPC_QPX_FF_Intrinsic<"qvfctidz">; + def int_ppc_qpx_qvfctiduz : PowerPC_QPX_FF_Intrinsic<"qvfctiduz">; + def int_ppc_qpx_qvfctiw : PowerPC_QPX_FF_Intrinsic<"qvfctiw">; + def int_ppc_qpx_qvfctiwu : PowerPC_QPX_FF_Intrinsic<"qvfctiwu">; + def int_ppc_qpx_qvfctiwz : PowerPC_QPX_FF_Intrinsic<"qvfctiwz">; + def int_ppc_qpx_qvfctiwuz : PowerPC_QPX_FF_Intrinsic<"qvfctiwuz">; + def int_ppc_qpx_qvfcfid : PowerPC_QPX_FF_Intrinsic<"qvfcfid">; + def int_ppc_qpx_qvfcfidu : PowerPC_QPX_FF_Intrinsic<"qvfcfidu">; + def int_ppc_qpx_qvfcfids : PowerPC_QPX_FF_Intrinsic<"qvfcfids">; + def int_ppc_qpx_qvfcfidus : PowerPC_QPX_FF_Intrinsic<"qvfcfidus">; + def int_ppc_qpx_qvfrsp : PowerPC_QPX_FF_Intrinsic<"qvfrsp">; + def int_ppc_qpx_qvfriz : PowerPC_QPX_FF_Intrinsic<"qvfriz">; + def int_ppc_qpx_qvfrin : PowerPC_QPX_FF_Intrinsic<"qvfrin">; + def int_ppc_qpx_qvfrip : PowerPC_QPX_FF_Intrinsic<"qvfrip">; + def int_ppc_qpx_qvfrim : PowerPC_QPX_FF_Intrinsic<"qvfrim">; + + // Move Instructions + def int_ppc_qpx_qvfneg : PowerPC_QPX_FF_Intrinsic<"qvfneg">; + def int_ppc_qpx_qvfabs : PowerPC_QPX_FF_Intrinsic<"qvfabs">; + def int_ppc_qpx_qvfnabs : PowerPC_QPX_FF_Intrinsic<"qvfnabs">; + def int_ppc_qpx_qvfcpsgn : PowerPC_QPX_FFF_Intrinsic<"qvfcpsgn">; + + // Compare Instructions + def int_ppc_qpx_qvftstnan : PowerPC_QPX_FFF_Intrinsic<"qvftstnan">; + def int_ppc_qpx_qvfcmplt : PowerPC_QPX_FFF_Intrinsic<"qvfcmplt">; + def int_ppc_qpx_qvfcmpgt : PowerPC_QPX_FFF_Intrinsic<"qvfcmpgt">; + def int_ppc_qpx_qvfcmpeq : PowerPC_QPX_FFF_Intrinsic<"qvfcmpeq">; + + // Load instructions + def int_ppc_qpx_qvlfd : PowerPC_QPX_Load_Intrinsic<"qvlfd">; + def int_ppc_qpx_qvlfda : PowerPC_QPX_Load_Intrinsic<"qvlfda">; + def int_ppc_qpx_qvlfs : PowerPC_QPX_Load_Intrinsic<"qvlfs">; + def int_ppc_qpx_qvlfsa : PowerPC_QPX_Load_Intrinsic<"qvlfsa">; + + def int_ppc_qpx_qvlfcda : PowerPC_QPX_Load_Intrinsic<"qvlfcda">; + def int_ppc_qpx_qvlfcd : PowerPC_QPX_Load_Intrinsic<"qvlfcd">; + def int_ppc_qpx_qvlfcsa : PowerPC_QPX_Load_Intrinsic<"qvlfcsa">; + def int_ppc_qpx_qvlfcs : PowerPC_QPX_Load_Intrinsic<"qvlfcs">; + def int_ppc_qpx_qvlfiwaa : PowerPC_QPX_Load_Intrinsic<"qvlfiwaa">; + def int_ppc_qpx_qvlfiwa : PowerPC_QPX_Load_Intrinsic<"qvlfiwa">; + def int_ppc_qpx_qvlfiwza : PowerPC_QPX_Load_Intrinsic<"qvlfiwza">; + def int_ppc_qpx_qvlfiwz : PowerPC_QPX_Load_Intrinsic<"qvlfiwz">; + + def int_ppc_qpx_qvlpcld : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcld">; + def int_ppc_qpx_qvlpcls : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcls">; + def int_ppc_qpx_qvlpcrd : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrd">; + def int_ppc_qpx_qvlpcrs : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrs">; + + // Store instructions + def int_ppc_qpx_qvstfd : PowerPC_QPX_Store_Intrinsic<"qvstfd">; + def int_ppc_qpx_qvstfda : PowerPC_QPX_Store_Intrinsic<"qvstfda">; + def int_ppc_qpx_qvstfs : PowerPC_QPX_Store_Intrinsic<"qvstfs">; + def int_ppc_qpx_qvstfsa : PowerPC_QPX_Store_Intrinsic<"qvstfsa">; + + def int_ppc_qpx_qvstfcda : PowerPC_QPX_Store_Intrinsic<"qvstfcda">; + def int_ppc_qpx_qvstfcd : PowerPC_QPX_Store_Intrinsic<"qvstfcd">; + def int_ppc_qpx_qvstfcsa : PowerPC_QPX_Store_Intrinsic<"qvstfcsa">; + def int_ppc_qpx_qvstfcs : PowerPC_QPX_Store_Intrinsic<"qvstfcs">; + def int_ppc_qpx_qvstfiwa : PowerPC_QPX_Store_Intrinsic<"qvstfiwa">; + def int_ppc_qpx_qvstfiw : PowerPC_QPX_Store_Intrinsic<"qvstfiw">; + + // Logical and permutation formation + def int_ppc_qpx_qvflogical : PowerPC_QPX_Intrinsic<"qvflogical", + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_qpx_qvgpci : PowerPC_QPX_Intrinsic<"qvgpci", + [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>; +} + diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index d99c42d..5055667 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -76,6 +76,9 @@ def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; +def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, + Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < "__builtin_amdgpu_read_workdim">; diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 59ff946..60deb32 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -453,19 +453,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; } // Conversion ops @@ -1363,6 +1350,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_load_ps_512 : GCCBuiltin<"__builtin_ia32_loadaps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_load_pd_512 : GCCBuiltin<"__builtin_ia32_loadapd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1389,6 +1382,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ps_512 : + GCCBuiltin<"__builtin_ia32_storeaps512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_pd_512 : + GCCBuiltin<"__builtin_ia32_storeapd512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; def int_x86_avx512_mask_store_ss : GCCBuiltin<"__builtin_ia32_storess_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], @@ -1572,19 +1573,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; @@ -1603,6 +1591,25 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Pack ops. @@ -1911,6 +1918,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; } // Gather ops @@ -2029,11 +2061,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2063,11 +2115,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2097,11 +2169,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2131,11 +2223,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2159,11 +2271,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2187,11 +2319,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -3003,6 +3155,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + + def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; @@ -3016,12 +3193,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -3102,22 +3281,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; -} - // Gather and Scatter ops let TargetPrefix = "x86" in { def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, @@ -3226,22 +3389,22 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_conflict_q_512 : GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_d_512 : GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_q_512 : GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; } // Vector blend @@ -3250,10 +3413,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">, Intrinsic<[llvm_v16i32_ty], @@ -3263,6 +3442,48 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + } let TargetPrefix = "x86" in { @@ -3307,29 +3528,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem ]>; def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; // 256-bit @@ -3360,29 +3581,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; // 128-bit @@ -3413,39 +3634,243 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; } +// Compress, Expand +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_compress_ps_512 : + GCCBuiltin<"__builtin_ia32_compresssf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_512 : + GCCBuiltin<"__builtin_ia32_compressdf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_256 : + GCCBuiltin<"__builtin_ia32_compresssf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_256 : + GCCBuiltin<"__builtin_ia32_compressdf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_128 : + GCCBuiltin<"__builtin_ia32_compresssf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_128 : + GCCBuiltin<"__builtin_ia32_compressdf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_ps_512 : + GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_512 : + GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_256 : + GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_256 : + GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_128 : + GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_128 : + GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + + def int_x86_avx512_mask_compress_d_512 : + GCCBuiltin<"__builtin_ia32_compresssi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_512 : + GCCBuiltin<"__builtin_ia32_compressdi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_256 : + GCCBuiltin<"__builtin_ia32_compresssi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_256 : + GCCBuiltin<"__builtin_ia32_compressdi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_128 : + GCCBuiltin<"__builtin_ia32_compresssi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_128 : + GCCBuiltin<"__builtin_ia32_compressdi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_d_512 : + GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_512 : + GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_256 : + GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_256 : + GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_128 : + GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_128 : + GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + +// expand + def int_x86_avx512_mask_expand_ps_512 : + GCCBuiltin<"__builtin_ia32_expandsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_512 : + GCCBuiltin<"__builtin_ia32_expanddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_256 : + GCCBuiltin<"__builtin_ia32_expandsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_256 : + GCCBuiltin<"__builtin_ia32_expanddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_128 : + GCCBuiltin<"__builtin_ia32_expandsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_128 : + GCCBuiltin<"__builtin_ia32_expanddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_ps_512 : + GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_512 : + GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_256 : + GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_256 : + GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_128 : + GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_128 : + GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + + def int_x86_avx512_mask_expand_d_512 : + GCCBuiltin<"__builtin_ia32_expandsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_512 : + GCCBuiltin<"__builtin_ia32_expanddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_256 : + GCCBuiltin<"__builtin_ia32_expandsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_256 : + GCCBuiltin<"__builtin_ia32_expanddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_128 : + GCCBuiltin<"__builtin_ia32_expandsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_128 : + GCCBuiltin<"__builtin_ia32_expanddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_d_512 : + GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_512 : + GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_256 : + GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_256 : + GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_128 : + GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_128 : + GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + +} // Misc. let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i8_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 2f18782..8c04b08 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -176,8 +176,8 @@ public: } private: - LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; - void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; + LLVMContext(LLVMContext&) = delete; + void operator=(LLVMContext&) = delete; /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h deleted file mode 100644 index cb18df8..0000000 --- a/include/llvm/IR/LeakDetector.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEAKDETECTOR_H -#define LLVM_IR_LEAKDETECTOR_H - -#include - -namespace llvm { - -class LLVMContext; -class Value; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - static void addGarbageObject(void *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - static void removeGarbageObject(void *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - - /// Overload the normal methods to work better with Value*'s because they are - /// by far the most common in LLVM. This does not affect the actual - /// functioning of this class, it just makes the warning messages nicer. - /// - static void addGarbageObject(const Value *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - static void removeGarbageObject(const Value *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - -private: - // If we are debugging, the actual implementations will be called... - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index c967a6b..6c04e9d 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -37,9 +37,10 @@ class PassManagerBase { public: virtual ~PassManagerBase(); - /// add - Add a pass to the queue of passes to run. This passes ownership of + /// Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass /// will be destroyed as well, so there is no need to delete the pass. This + /// may even destroy the pass right away if it is found to be redundant. This /// implies that all passes MUST be allocated with 'new'. virtual void add(Pass *P) = 0; }; @@ -51,10 +52,6 @@ public: PassManager(); ~PassManager(); - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep track of @@ -75,11 +72,6 @@ public: explicit FunctionPassManager(Module *M); ~FunctionPassManager(); - /// add - Add a pass to the queue of passes to run. This passes - /// ownership of the Pass to the PassManager. When the - /// PassManager_X is destroyed, the pass will be destroyed as well, so - /// there is no need to delete the pass. - /// This implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index ab500a1..7f7889a 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -195,6 +195,9 @@ public: /// then return NULL. Pass *findAnalysisPass(AnalysisID AID); + /// Retrieve the PassInfo for an analysis. + const PassInfo *findAnalysisPassInfo(AnalysisID AID) const; + /// Find analysis usage information for the pass P. AnalysisUsage *findAnalysisUsage(Pass *P); @@ -251,6 +254,12 @@ private: SmallVector ImmutablePasses; DenseMap AnUsageMap; + + /// Collection of PassInfo objects found via analysis IDs and in this top + /// level manager. This is used to memoize queries to the pass registry. + /// FIXME: This is an egregious hack because querying the pass registry is + /// either slow or racy. + mutable DenseMap AnalysisPassInfos; }; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index e2e4912..52db1c3 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -41,14 +41,12 @@ namespace llvm { // class PassNameParser : public PassRegistrationListener, public cl::parser { - cl::Option *Opt; public: - PassNameParser(); + PassNameParser(cl::Option &O); virtual ~PassNameParser(); - void initialize(cl::Option &O) { - Opt = &O; - cl::parser::initialize(O); + void initialize() { + cl::parser::initialize(); // Add all of the passes to the map that got initialized before 'this' did. enumeratePasses(); @@ -69,7 +67,7 @@ public: // Implement the PassRegistrationListener callbacks used to populate our map // void passRegistered(const PassInfo *P) override { - if (ignorablePass(P) || !Opt) return; + if (ignorablePass(P)) return; if (findOption(P->getPassArgument()) != getNumOptions()) { errs() << "Two passes with the same argument (-" << P->getPassArgument() << ") attempted to be registered!\n"; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index d29512c..51b8b02 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -24,6 +24,8 @@ namespace llvm { class APInt; template class ArrayRef; class LLVMContext; +class Constant; +class ConstantAsMetadata; class MDNode; class MDString; @@ -36,6 +38,9 @@ public: /// \brief Return the given string as metadata. MDString *createString(StringRef Str); + /// \brief Return the given constant as metadata. + ConstantAsMetadata *createConstant(Constant *C); + //===------------------------------------------------------------------===// // FPMath metadata. //===------------------------------------------------------------------===// @@ -62,6 +67,9 @@ public: /// \brief Return metadata describing the range [Lo, Hi). MDNode *createRange(const APInt &Lo, const APInt &Hi); + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(Constant *Lo, Constant *Hi); + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def new file mode 100644 index 0000000..66589e0 --- /dev/null +++ b/include/llvm/IR/Metadata.def @@ -0,0 +1,99 @@ +//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of metadata. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ + defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ + defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ + defined HANDLE_SPECIALIZED_MDNODE_BRANCH) +#error "Missing macro definition of HANDLE_METADATA*" +#endif + +// Handler for all types of metadata. +#ifndef HANDLE_METADATA +#define HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_LEAF +#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for non-leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_BRANCH +#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF +#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +#endif + +// Handler for non-leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_BRANCH +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +// Handler for specialized leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for specialized non-leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH +#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) +#endif + +HANDLE_METADATA_LEAF(MDString) +HANDLE_METADATA_BRANCH(ValueAsMetadata) +HANDLE_METADATA_LEAF(ConstantAsMetadata) +HANDLE_METADATA_LEAF(LocalAsMetadata) +HANDLE_MDNODE_BRANCH(MDNode) +HANDLE_MDNODE_LEAF(MDTuple) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocation) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DebugNode) +HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDebugNode) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDBasicType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDDerivedTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDDerivedType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDCompositeTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompileUnit) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDNamespace) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDTemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDExpression) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDImportedEntity) + +#undef HANDLE_METADATA +#undef HANDLE_METADATA_LEAF +#undef HANDLE_METADATA_BRANCH +#undef HANDLE_MDNODE_LEAF +#undef HANDLE_MDNODE_BRANCH +#undef HANDLE_SPECIALIZED_MDNODE_LEAF +#undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index a056b0d..ff8f837 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -1,4 +1,4 @@ -//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,11 +18,13 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/MetadataTracking.h" #include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" +#include namespace llvm { class LLVMContext; @@ -38,20 +40,422 @@ enum LLVMConstants : uint32_t { /// \brief Root of the metadata hierarchy. /// /// This is a root class for typeless data in the IR. -/// -/// TODO: Detach from the Value hierarchy. -class Metadata : public Value { +class Metadata { + friend class ReplaceableMetadataImpl; + + /// \brief RTTI. + const unsigned char SubclassID; + +protected: + /// \brief Active type of storage. + enum StorageType { Uniqued, Distinct, Temporary }; + + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + unsigned Storage : 2; + // TODO: expose remaining bits to subclasses. + + unsigned short SubclassData16; + unsigned SubclassData32; + +public: + enum MetadataKind { + MDTupleKind, + MDLocationKind, + GenericDebugNodeKind, + MDSubrangeKind, + MDEnumeratorKind, + MDBasicTypeKind, + MDDerivedTypeKind, + MDCompositeTypeKind, + MDSubroutineTypeKind, + MDFileKind, + MDCompileUnitKind, + MDSubprogramKind, + MDLexicalBlockKind, + MDLexicalBlockFileKind, + MDNamespaceKind, + MDTemplateTypeParameterKind, + MDTemplateValueParameterKind, + MDGlobalVariableKind, + MDLocalVariableKind, + MDExpressionKind, + MDObjCPropertyKind, + MDImportedEntityKind, + ConstantAsMetadataKind, + LocalAsMetadataKind, + MDStringKind + }; + protected: - Metadata(LLVMContext &Context, unsigned ID); + Metadata(unsigned ID, StorageType Storage) + : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { + } + ~Metadata() {} + + /// \brief Default handling of a changed operand, which asserts. + /// + /// If subclasses pass themselves in as owners to a tracking node reference, + /// they must provide an implementation of this method. + void handleChangedOperand(void *, Metadata *) { + llvm_unreachable("Unimplemented in Metadata subclass"); + } + +public: + unsigned getMetadataID() const { return SubclassID; } + + /// \brief User-friendly dump. + void dump() const; + void print(raw_ostream &OS) const; + void printAsOperand(raw_ostream &OS, bool PrintType = true, + const Module *M = nullptr) const; +}; + +#define HANDLE_METADATA(CLASS) class CLASS; +#include "llvm/IR/Metadata.def" + +inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { + MD.print(OS); + return OS; +} + +/// \brief Metadata wrapper in the Value hierarchy. +/// +/// A member of the \a Value hierarchy to represent a reference to metadata. +/// This allows, e.g., instrinsics to have metadata as operands. +/// +/// Notably, this is the only thing in either hierarchy that is allowed to +/// reference \a LocalAsMetadata. +class MetadataAsValue : public Value { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Metadata *MD; + + MetadataAsValue(Type *Ty, Metadata *MD); + ~MetadataAsValue(); + + /// \brief Drop use of metadata (during teardown). + void dropUse() { MD = nullptr; } public: + static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); + static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); + Metadata *getMetadata() const { return MD; } + static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal || - V->getValueID() == MDNodeFwdDeclVal || - V->getValueID() == MDStringVal; + return V->getValueID() == MetadataAsValueVal; } + +private: + void handleChangedMetadata(Metadata *MD); + void track(); + void untrack(); }; +/// \brief Shared implementation of use-lists for replaceable metadata. +/// +/// Most metadata cannot be RAUW'ed. This is a shared implementation of +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). +class ReplaceableMetadataImpl { + friend class MetadataTracking; + +public: + typedef MetadataTracking::OwnerTy OwnerTy; + +private: + LLVMContext &Context; + uint64_t NextIndex; + SmallDenseMap, 4> UseMap; + +public: + ReplaceableMetadataImpl(LLVMContext &Context) + : Context(Context), NextIndex(0) {} + ~ReplaceableMetadataImpl() { + assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); + } + + LLVMContext &getContext() const { return Context; } + + /// \brief Replace all uses of this with MD. + /// + /// Replace all uses of this with \c MD, which is allowed to be null. + void replaceAllUsesWith(Metadata *MD); + + /// \brief Resolve all uses of this. + /// + /// Resolve all uses of this, turning off RAUW permanently. If \c + /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand + /// is resolved. + void resolveAllUses(bool ResolveUsers = true); + +private: + void addRef(void *Ref, OwnerTy Owner); + void dropRef(void *Ref); + void moveRef(void *Ref, void *New, const Metadata &MD); + + static ReplaceableMetadataImpl *get(Metadata &MD); +}; + +/// \brief Value wrapper in the Metadata hierarchy. +/// +/// This is a custom value handle that allows other metadata to refer to +/// classes in the Value hierarchy. +/// +/// Because of full uniquing support, each value is only wrapped by a single \a +/// ValueAsMetadata object, so the lookup maps are far more efficient than +/// those using ValueHandleBase. +class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Value *V; + + /// \brief Drop users without RAUW (during teardown). + void dropUsers() { + ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + } + +protected: + ValueAsMetadata(unsigned ID, Value *V) + : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { + assert(V && "Expected valid value"); + } + ~ValueAsMetadata() {} + +public: + static ValueAsMetadata *get(Value *V); + static ConstantAsMetadata *getConstant(Value *C) { + return cast(get(C)); + } + static LocalAsMetadata *getLocal(Value *Local) { + return cast(get(Local)); + } + + static ValueAsMetadata *getIfExists(Value *V); + static ConstantAsMetadata *getConstantIfExists(Value *C) { + return cast_or_null(getIfExists(C)); + } + static LocalAsMetadata *getLocalIfExists(Value *Local) { + return cast_or_null(getIfExists(Local)); + } + + Value *getValue() const { return V; } + Type *getType() const { return V->getType(); } + LLVMContext &getContext() const { return V->getContext(); } + + static void handleDeletion(Value *V); + static void handleRAUW(Value *From, Value *To); + +protected: + /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// + /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped + /// \a Value gets RAUW'ed and the target already exists, this is used to + /// merge the two metadata nodes. + void replaceAllUsesWith(Metadata *MD) { + ReplaceableMetadataImpl::replaceAllUsesWith(MD); + } + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind || + MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class ConstantAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + ConstantAsMetadata(Constant *C) + : ValueAsMetadata(ConstantAsMetadataKind, C) {} + +public: + static ConstantAsMetadata *get(Constant *C) { + return ValueAsMetadata::getConstant(C); + } + static ConstantAsMetadata *getIfExists(Constant *C) { + return ValueAsMetadata::getConstantIfExists(C); + } + + Constant *getValue() const { + return cast(ValueAsMetadata::getValue()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class LocalAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + LocalAsMetadata(Value *Local) + : ValueAsMetadata(LocalAsMetadataKind, Local) { + assert(!isa(Local) && "Expected local value"); + } + +public: + static LocalAsMetadata *get(Value *Local) { + return ValueAsMetadata::getLocal(Local); + } + static LocalAsMetadata *getIfExists(Value *Local) { + return ValueAsMetadata::getLocalIfExists(Local); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind; + } +}; + +/// \brief Transitional API for extracting constants from Metadata. +/// +/// This namespace contains transitional functions for metadata that points to +/// \a Constants. +/// +/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode +/// operands could refer to any \a Value. There's was a lot of code like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining +/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three +/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and +/// cast in the \a Value hierarchy. Besides creating boiler-plate, this +/// requires subtle control flow changes. +/// +/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, +/// so that metadata can refer to numbers without traversing a bridge to the \a +/// Value hierarchy. In this final state, the code above would look like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *MI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// The API in this namespace supports the transition. \a MDInt doesn't exist +/// yet, and even once it does, changing each metadata schema to use it is its +/// own mini-project. In the meantime this API prevents us from introducing +/// complex and bug-prone control flow that will disappear in the end. In +/// particular, the above code looks like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = mdconst::dyn_extract(N->getOperand(2)); +/// \endcode +/// +/// The full set of provided functions includes: +/// +/// mdconst::hasa <=> isa +/// mdconst::extract <=> cast +/// mdconst::extract_or_null <=> cast_or_null +/// mdconst::dyn_extract <=> dyn_cast +/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null +/// +/// The target of the cast must be a subclass of \a Constant. +namespace mdconst { + +namespace detail { +template T &make(); +template struct HasDereference { + typedef char Yes[1]; + typedef char No[2]; + template struct SFINAE {}; + + template + static Yes &hasDereference(SFINAE(*make()))> * = 0); + template static No &hasDereference(...); + + static const bool value = + sizeof(hasDereference(nullptr)) == sizeof(Yes); +}; +template struct IsValidPointer { + static const bool value = std::is_base_of::value && + HasDereference::value; +}; +template struct IsValidReference { + static const bool value = std::is_base_of::value && + std::is_convertible::value; +}; +} // end namespace detail + +/// \brief Check whether Metadata has a Value. +/// +/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of +/// type \c X. +template +inline typename std::enable_if::value, bool>::type +hasa(Y &&MD) { + assert(MD && "Null pointer sent into hasa"); + if (auto *V = dyn_cast(MD)) + return isa(V->getValue()); + return false; +} +template +inline + typename std::enable_if::value, bool>::type + hasa(Y &MD) { + return hasa(&MD); +} + +/// \brief Extract a Value from Metadata. +/// +/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. +template +inline typename std::enable_if::value, X *>::type +extract(Y &&MD) { + return cast(cast(MD)->getValue()); +} +template +inline + typename std::enable_if::value, X *>::type + extract(Y &MD) { + return extract(&MD); +} + +/// \brief Extract a Value from Metadata, allowing null. +/// +/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +extract_or_null(Y &&MD) { + if (auto *V = cast_or_null(MD)) + return cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass. +template +inline typename std::enable_if::value, X *>::type +dyn_extract(Y &&MD) { + if (auto *V = dyn_cast(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any, allowing null. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +dyn_extract_or_null(Y &&MD) { + if (auto *V = dyn_cast_or_null(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +} // end namespace mdconst + //===----------------------------------------------------------------------===// /// \brief A single uniqued string. /// @@ -60,14 +464,13 @@ public: class MDString : public Metadata { friend class StringMapEntry; - virtual void anchor(); - MDString(const MDString &) LLVM_DELETED_FUNCTION; - - explicit MDString(LLVMContext &Context) - : Metadata(Context, Value::MDStringVal) {} + MDString(const MDString &) = delete; + MDString &operator=(MDString &&) = delete; + MDString &operator=(const MDString &) = delete; - /// \brief Shadow Value::getName() to prevent its use. - StringRef getName() const LLVM_DELETED_FUNCTION; + StringMapEntry *Entry; + MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {} public: static MDString *get(LLVMContext &Context, StringRef Str); @@ -87,9 +490,12 @@ public: /// \brief Pointer to one byte past the end of the string. iterator end() const { return getString().end(); } + const unsigned char *bytes_begin() const { return getString().bytes_begin(); } + const unsigned char *bytes_end() const { return getString().bytes_end(); } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == MDStringVal; + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDStringKind; } }; @@ -106,7 +512,7 @@ struct AAMDNodes { bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + explicit operator bool() const { return TBAA || Scope || NoAlias; } /// \brief The tag for type-based alias analysis. MDNode *TBAA; @@ -137,21 +543,171 @@ struct DenseMapInfo { } }; -class MDNodeOperand; +/// \brief Tracking metadata reference owned by Metadata. +/// +/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance +/// of \a Metadata, which has the option of registering itself for callbacks to +/// re-unique itself. +/// +/// In particular, this is used by \a MDNode. +class MDOperand { + MDOperand(MDOperand &&) = delete; + MDOperand(const MDOperand &) = delete; + MDOperand &operator=(MDOperand &&) = delete; + MDOperand &operator=(const MDOperand &) = delete; -//===----------------------------------------------------------------------===// -/// \brief Tuple of metadata. + Metadata *MD; + +public: + MDOperand() : MD(nullptr) {} + ~MDOperand() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD, Metadata *Owner) { + untrack(); + this->MD = MD; + track(Owner); + } + +private: + void track(Metadata *Owner) { + if (MD) { + if (Owner) + MetadataTracking::track(this, *MD, *Owner); + else + MetadataTracking::track(MD); + } + } + void untrack() { + assert(static_cast(this) == &MD && "Expected same address"); + if (MD) + MetadataTracking::untrack(MD); + } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } +}; + +/// \brief Pointer to the context, with optional RAUW support. +/// +/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer +/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). +class ContextAndReplaceableUses { + PointerUnion Ptr; + + ContextAndReplaceableUses() = delete; + ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; + ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses & + operator=(const ContextAndReplaceableUses &) = delete; + +public: + ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} + ContextAndReplaceableUses( + std::unique_ptr ReplaceableUses) + : Ptr(ReplaceableUses.release()) { + assert(getReplaceableUses() && "Expected non-null replaceable uses"); + } + ~ContextAndReplaceableUses() { delete getReplaceableUses(); } + + operator LLVMContext &() { return getContext(); } + + /// \brief Whether this contains RAUW support. + bool hasReplaceableUses() const { + return Ptr.is(); + } + LLVMContext &getContext() const { + if (hasReplaceableUses()) + return getReplaceableUses()->getContext(); + return *Ptr.get(); + } + ReplaceableMetadataImpl *getReplaceableUses() const { + if (hasReplaceableUses()) + return Ptr.get(); + return nullptr; + } + + /// \brief Assign RAUW support to this. + /// + /// Make this replaceable, taking ownership of \c ReplaceableUses (which must + /// not be null). + void + makeReplaceable(std::unique_ptr ReplaceableUses) { + assert(ReplaceableUses && "Expected non-null replaceable uses"); + assert(&ReplaceableUses->getContext() == &getContext() && + "Expected same context"); + delete getReplaceableUses(); + Ptr = ReplaceableUses.release(); + } + + /// \brief Drop RAUW support. + /// + /// Cede ownership of RAUW support, returning it. + std::unique_ptr takeReplaceableUses() { + assert(hasReplaceableUses() && "Expected to own replaceable uses"); + std::unique_ptr ReplaceableUses( + getReplaceableUses()); + Ptr = &ReplaceableUses->getContext(); + return ReplaceableUses; + } +}; + +struct TempMDNodeDeleter { + inline void operator()(MDNode *Node) const; +}; + +#define HANDLE_MDNODE_LEAF(CLASS) \ + typedef std::unique_ptr Temp##CLASS; +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#include "llvm/IR/Metadata.def" + +/// \brief Metadata node. +/// +/// Metadata nodes can be uniqued, like constants, or distinct. Temporary +/// metadata nodes (with full support for RAUW) can be used to delay uniquing +/// until forward references are known. The basic metadata node is an \a +/// MDTuple. +/// +/// There is limited support for RAUW at construction time. At construction +/// time, if any operand is a temporary node (or an unresolved uniqued node, +/// which indicates a transitive temporary operand), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop RAUW +/// support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle once all temporary nodes have been +/// replaced. class MDNode : public Metadata { - MDNode(const MDNode &) LLVM_DELETED_FUNCTION; - void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - friend class MDNodeOperand; + friend class ReplaceableMetadataImpl; friend class LLVMContextImpl; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + + MDNode(const MDNode &) = delete; + void operator=(const MDNode &) = delete; + void *operator new(size_t) = delete; + + unsigned NumOperands; + unsigned NumUnresolved; protected: - void *operator new(size_t Size, unsigned NumOps); + ContextAndReplaceableUses Context; - /// \brief Required by std, but never called. + void *operator new(size_t Size, unsigned NumOps); void operator delete(void *Mem); /// \brief Required by std, but never called. @@ -164,83 +720,188 @@ protected: llvm_unreachable("Constructor throws?"); } - /// \brief Subclass data enums. - enum { - /// FunctionLocalBit - This bit is set if this MDNode is function local. - /// This is true when it (potentially transitively) contains a reference to - /// something in a function, like an argument, basicblock, or instruction. - FunctionLocalBit = 1 << 0, + MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef Ops1, ArrayRef Ops2 = None); + ~MDNode() {} - /// NotUniquedBit - This is set on MDNodes that are not uniqued because they - /// have a null operand. - NotUniquedBit = 1 << 1 - }; + void dropAllReferences(); - /// \brief FunctionLocal enums. - enum FunctionLocalness { - FL_Unknown = -1, - FL_No = 0, - FL_Yes = 1 - }; + MDOperand *mutable_begin() { return mutable_end() - NumOperands; } + MDOperand *mutable_end() { return reinterpret_cast(this); } - /// \brief Replace each instance of the given operand with a new value. - void replaceOperand(MDNodeOperand *Op, Value *NewVal); +public: + static inline MDTuple *get(LLVMContext &Context, ArrayRef MDs); + static inline MDTuple *getIfExists(LLVMContext &Context, + ArrayRef MDs); + static inline MDTuple *getDistinct(LLVMContext &Context, + ArrayRef MDs); + static inline TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef MDs); - MDNode(LLVMContext &C, unsigned ID, ArrayRef Vals, - bool isFunctionLocal); - ~MDNode() {} + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; - static MDNode *getMDNode(LLVMContext &C, ArrayRef Vals, - FunctionLocalness FL, bool Insert = true); -public: - static MDNode *get(LLVMContext &Context, ArrayRef Vals); - /// \brief Construct MDNode with an explicit function-localness. + /// \brief Deallocate a node created by getTemporary. /// - /// Don't analyze Vals; trust isFunctionLocal. - static MDNode *getWhenValsUnresolved(LLVMContext &Context, - ArrayRef Vals, - bool isFunctionLocal); + /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + /// references will be reset. + static void deleteTemporary(MDNode *N); - static MDNode *getIfExists(LLVMContext &Context, ArrayRef Vals); + LLVMContext &getContext() const { return Context.getContext(); } + + /// \brief Replace a specific operand. + void replaceOperandWith(unsigned I, Metadata *New); - /// \brief Return a temporary MDNode + /// \brief Check if node is fully resolved. /// - /// For use in constructing cyclic MDNode structures. A temporary MDNode is - /// not uniqued, may be RAUW'd, and must be manually deleted with - /// deleteTemporary. - static MDNode *getTemporary(LLVMContext &Context, ArrayRef Vals); + /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), + /// this always returns \c true. + /// + /// If \a isUniqued(), returns \c true if this has already dropped RAUW + /// support (because all operands are resolved). + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !Context.hasReplaceableUses(); } - /// \brief Deallocate a node created by getTemporary. + bool isUniqued() const { return Storage == Uniqued; } + bool isDistinct() const { return Storage == Distinct; } + bool isTemporary() const { return Storage == Temporary; } + + /// \brief RAUW a temporary. /// - /// The node must not have any users. - static void deleteTemporary(MDNode *N); + /// \pre \a isTemporary() must be \c true. + void replaceAllUsesWith(Metadata *MD) { + assert(isTemporary() && "Expected temporary node"); + assert(!isResolved() && "Expected RAUW support"); + Context.getReplaceableUses()->replaceAllUsesWith(MD); + } - /// \brief Replace a specific operand. - void replaceOperandWith(unsigned i, Value *NewVal); + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). + void resolveCycles(); - /// \brief Return specified operand. - Value *getOperand(unsigned i) const LLVM_READONLY; + /// \brief Replace a temporary node with a permanent one. + /// + /// Try to create a uniqued version of \c N -- in place, if possible -- and + /// return it. If \c N cannot be uniqued, return a distinct node instead. + template + static typename std::enable_if::value, T *>::type + replaceWithPermanent(std::unique_ptr N) { + return cast(N.release()->replaceWithPermanentImpl()); + } - /// \brief Return number of MDNode operands. - unsigned getNumOperands() const { return NumOperands; } + /// \brief Replace a temporary node with a uniqued one. + /// + /// Create a uniqued version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + /// + /// \pre N does not self-reference. + template + static typename std::enable_if::value, T *>::type + replaceWithUniqued(std::unique_ptr N) { + return cast(N.release()->replaceWithUniquedImpl()); + } - /// \brief Return whether MDNode is local to a function. - bool isFunctionLocal() const { - return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + /// \brief Replace a temporary node with a distinct one. + /// + /// Create a distinct version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + template + static typename std::enable_if::value, T *>::type + replaceWithDistinct(std::unique_ptr N) { + return cast(N.release()->replaceWithDistinctImpl()); } - /// \brief Return the first function-local operand's function. +private: + MDNode *replaceWithPermanentImpl(); + MDNode *replaceWithUniquedImpl(); + MDNode *replaceWithDistinctImpl(); + +protected: + /// \brief Set an operand. + /// + /// Sets the operand directly, without worrying about uniquing. + void setOperand(unsigned I, Metadata *New); + + void storeDistinctInContext(); + template + static T *storeImpl(T *N, StorageType Storage, StoreT &Store); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + unsigned countUnresolvedOperands(); + + /// \brief Mutate this to be "uniqued". /// - /// If this metadata is function-local and recursively has a function-local - /// operand, return the first such operand's parent function. Otherwise, - /// return null. getFunction() should not be used for performance- critical - /// code because it recursively visits all the MDNode's operands. - const Function *getFunction() const; + /// Mutate this so that \a isUniqued(). + /// \pre \a isTemporary(). + /// \pre already added to uniquing set. + void makeUniqued(); + + /// \brief Mutate this to be "distinct". + /// + /// Mutate this so that \a isDistinct(). + /// \pre \a isTemporary(). + void makeDistinct(); + + void deleteAsSubclass(); + MDNode *uniquify(); + void eraseFromStore(); + + template struct HasCachedHash; + template + static void dispatchRecalculateHash(NodeTy *N, std::true_type) { + N->recalculateHash(); + } + template + static void dispatchRecalculateHash(NodeTy *N, std::false_type) {} + template + static void dispatchResetHash(NodeTy *N, std::true_type) { + N->setHash(0); + } + template + static void dispatchResetHash(NodeTy *N, std::false_type) {} + +public: + typedef const MDOperand *op_iterator; + typedef iterator_range op_range; + + op_iterator op_begin() const { + return const_cast(this)->mutable_begin(); + } + op_iterator op_end() const { + return const_cast(this)->mutable_end(); + } + op_range operands() const { return op_range(op_begin(), op_end()); } + + const MDOperand &getOperand(unsigned I) const { + assert(I < NumOperands && "Out of range"); + return op_begin()[I]; + } + + /// \brief Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal || - V->getValueID() == MDNodeFwdDeclVal; + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return true; +#include "llvm/IR/Metadata.def" + } } /// \brief Check whether MDNode is a vtable access. @@ -250,72 +911,91 @@ public: static MDNode *concatenate(MDNode *A, MDNode *B); static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); - static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); - -protected: - bool isNotUniqued() const { - return (getSubclassDataFromValue() & NotUniquedBit) != 0; - } - void setIsNotUniqued(); - - // Shadow Value::setValueSubclassData with a private forwarding method so that - // any future subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } + static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); }; -/// \brief Generic metadata node. -/// -/// Generic metadata nodes, with opt-out support for uniquing. -/// -/// Although nodes are uniqued by default, \a GenericMDNode has no support for -/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing -/// collision, the uniquing bit is dropped. +/// \brief Tuple of metadata. /// -/// TODO: Make uniquing opt-out (status: mandatory, sometimes dropped). -/// TODO: Drop support for RAUW. -class GenericMDNode : public MDNode { - friend class MDNode; +/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by +/// default based on their operands. +class MDTuple : public MDNode { friend class LLVMContextImpl; + friend class MDNode; + + MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, + ArrayRef Vals) + : MDNode(C, MDTupleKind, Storage, Vals) { + setHash(Hash); + } + ~MDTuple() { dropAllReferences(); } - unsigned Hash; + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); - GenericMDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) - : MDNode(C, GenericMDNodeVal, Vals, isFunctionLocal), Hash(0) {} - ~GenericMDNode(); + static MDTuple *getImpl(LLVMContext &Context, ArrayRef MDs, + StorageType Storage, bool ShouldCreate = true); - void dropAllReferences(); + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector(op_begin(), op_end())); + } public: /// \brief Get the hash, if any. - unsigned getHash() const { return Hash; } + unsigned getHash() const { return SubclassData32; } - static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal; + static MDTuple *get(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Uniqued); + } + static MDTuple *getIfExists(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); } -}; -/// \brief Forward declaration of metadata. -/// -/// Forward declaration of metadata, in the form of a metadata node. Unlike \a -/// GenericMDNode, this class has support for RAUW and is suitable for forward -/// references. -class MDNodeFwdDecl : public MDNode { - friend class MDNode; + /// \brief Return a distinct node. + /// + /// Return a distinct node -- i.e., a node that is not uniqued. + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Distinct); + } - MDNodeFwdDecl(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) - : MDNode(C, MDNodeFwdDeclVal, Vals, isFunctionLocal) {} - ~MDNodeFwdDecl() {} + /// \brief Return a temporary node. + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return TempMDTuple(getImpl(Context, MDs, Temporary)); + } -public: - static bool classof(const Value *V) { - return V->getValueID() == MDNodeFwdDeclVal; + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind; } }; +MDTuple *MDNode::get(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::get(Context, MDs); +} +MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getIfExists(Context, MDs); +} +MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getDistinct(Context, MDs); +} +TempMDTuple MDNode::getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return MDTuple::getTemporary(Context, MDs); +} + +void TempMDNodeDeleter::operator()(MDNode *Node) const { + MDNode::deleteTemporary(Node); +} + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// @@ -328,11 +1008,11 @@ class NamedMDNode : public ilist_node { friend struct ilist_traits; friend class LLVMContextImpl; friend class Module; - NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; + NamedMDNode(const NamedMDNode &) = delete; std::string Name; Module *Parent; - void *Operands; // SmallVector, 4> + void *Operands; // SmallVector void setParent(Module *M) { Parent = M; } @@ -390,6 +1070,7 @@ public: MDNode *getOperand(unsigned i) const; unsigned getNumOperands() const; void addOperand(MDNode *M); + void setOperand(unsigned I, MDNode *New); StringRef getName() const; void print(raw_ostream &ROS) const; void dump() const; diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h new file mode 100644 index 0000000..541d9b3 --- /dev/null +++ b/include/llvm/IR/MetadataTracking.h @@ -0,0 +1,99 @@ +//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Low-level functions to enable tracking of metadata that could RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATATRACKING_H +#define LLVM_IR_METADATATRACKING_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class Metadata; +class MetadataAsValue; + +/// \brief API for tracking metadata references through RAUW and deletion. +/// +/// Shared API for updating \a Metadata pointers in subclasses that support +/// RAUW. +/// +/// This API is not meant to be used directly. See \a TrackingMDRef for a +/// user-friendly tracking reference. +class MetadataTracking { +public: + /// \brief Track the reference to metadata. + /// + /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD + /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets + /// deleted, \c MD will be set to \c nullptr. + /// + /// If tracking isn't supported, \c *MD will not change. + /// + /// \return true iff tracking is supported by \c MD. + static bool track(Metadata *&MD) { + return track(&MD, *MD, static_cast(nullptr)); + } + + /// \brief Track the reference to metadata for \a Metadata. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, Metadata &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Track the reference to metadata for \a MetadataAsValue. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Stop tracking a reference to metadata. + /// + /// Stops \c *MD from tracking \c MD. + static void untrack(Metadata *&MD) { untrack(&MD, *MD); } + static void untrack(void *Ref, Metadata &MD); + + /// \brief Move tracking from one reference to another. + /// + /// Semantically equivalent to \c untrack(MD) followed by \c track(New), + /// except that ownership callbacks are maintained. + /// + /// Note: it is an error if \c *MD does not equal \c New. + /// + /// \return true iff tracking is supported by \c MD. + static bool retrack(Metadata *&MD, Metadata *&New) { + return retrack(&MD, *MD, &New); + } + static bool retrack(void *Ref, Metadata &MD, void *New); + + /// \brief Check whether metadata is replaceable. + static bool isReplaceable(const Metadata &MD); + + typedef PointerUnion OwnerTy; + +private: + /// \brief Track a reference to metadata for an owner. + /// + /// Generalized version of tracking. + static bool track(void *Ref, Metadata &MD, OwnerTy Owner); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 7fff80a..62f4194 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -33,8 +33,6 @@ class GVMaterializer; class LLVMContext; class RandomNumberGenerator; class StructType; -template struct DenseMapInfo; -template class DenseMap; template<> struct ilist_traits : public SymbolTableListTraits { @@ -150,7 +148,7 @@ public: /// The named metadata iterators. typedef NamedMDListType::iterator named_metadata_iterator; - /// The named metadata constant interators. + /// The named metadata constant iterators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; /// This enumeration defines the supported behaviors of module flags. @@ -190,16 +188,16 @@ public: ModFlagBehaviorLastVal = AppendUnique }; - /// Checks if Value represents a valid ModFlagBehavior, and stores the + /// Checks if Metadata represents a valid ModFlagBehavior, and stores the /// converted result in MFB. - static bool isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB); + static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); struct ModuleFlagEntry { ModFlagBehavior Behavior; MDString *Key; - Value *Val; - ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V) - : Behavior(B), Key(K), Val(V) {} + Metadata *Val; + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) + : Behavior(B), Key(K), Val(V) {} }; /// @} @@ -219,9 +217,8 @@ private: Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on + ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - // Allow lazy initialization in const method. - mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. // We need to keep the string because the C API expects us to own the string // representation. @@ -251,6 +248,12 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } + /// \brief Get a short "name" for the module. + /// + /// This is useful for debugging or logging. It is essentially a convenience + /// wrapper around getModuleIdentifier(). + StringRef getName() const { return ModuleID; } + /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). const std::string &getDataLayoutStr() const { return DataLayoutStr; } @@ -270,10 +273,16 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } - /// Get the RandomNumberGenerator for this module. The RNG can be - /// seeded via -rng-seed= and is salted with the ModuleID. - /// The returned RNG should not be shared across threads. - RandomNumberGenerator &getRNG() const; + /// Get a RandomNumberGenerator salted for use with this module. The + /// RNG can be seeded via -rng-seed= and is salted with the + /// ModuleID and the provided pass salt. The returned RNG should not + /// be shared across threads or passes. + /// + /// A unique RNG per pass ensures a reproducible random stream even + /// when other randomness consuming passes are added or removed. In + /// addition, the random stream will be reproducible across LLVM + /// versions when the pass does not change. + RandomNumberGenerator *createRNG(const Pass* P) const; /// @} /// @name Module Level Mutators @@ -327,6 +336,8 @@ public: /// name. StructType *getTypeByName(StringRef Name) const; + std::vector getIdentifiedStructTypes() const; + /// @} /// @name Function Accessors /// @{ @@ -441,7 +452,7 @@ public: /// Return the corresponding value if Key appears in module flags, otherwise /// return null. - Value *getModuleFlag(StringRef Key) const; + Metadata *getModuleFlag(StringRef Key) const; /// Returns the NamedMDNode in the module that represents module-level flags. /// This method returns null if there are no module-level flags. @@ -454,7 +465,8 @@ public: /// Add a module-level flag to the module-level flags metadata. It will create /// the module-level flags named metadata if it doesn't already exist. - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); void addModuleFlag(MDNode *Node); @@ -483,7 +495,7 @@ public: std::error_code materialize(GlobalValue *GV); /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized - /// lazily. If !isDematerializable(), this method is a noop. + /// lazily. If !isDematerializable(), this method is a no-op. void Dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. @@ -618,6 +630,15 @@ public: named_metadata_end()); } + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + /// @} /// @name Utility functions for printing and dumping Module objects /// @{ diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 0933f21..46935ce 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -34,12 +34,12 @@ class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself // instantiated. - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; - Operator() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + Operator() = delete; protected: - // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // NOTE: Cannot use = delete because it's not legal to delete // an overridden method that's not deleted in the base class. Cannot leave // this unimplemented because that leads to an ODR-violation. ~Operator(); @@ -504,6 +504,20 @@ public: } }; +class BitCastOperator + : public ConcreteOperator { + friend class BitCastInst; + friend class ConstantExpr; + +public: + Type *getSrcTy() const { + return getOperand(0)->getType(); + } + + Type *getDestTy() const { + return getType(); + } +}; } // End llvm namespace diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 45985e1..c92e7c9 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -43,6 +43,9 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManagerInternal.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/type_traits.h" #include #include @@ -91,9 +94,12 @@ public: } /// \brief Mark a particular pass as preserved, adding it to the set. - template void preserve() { + template void preserve() { preserve(PassT::ID()); } + + /// \brief Mark an abstract PassID as preserved, adding it to the set. + void preserve(void *PassID) { if (!areAllPreserved()) - PreservedPassIDs.insert(PassT::ID()); + PreservedPassIDs.insert(PassID); } /// \brief Intersect this set with another in place. @@ -140,408 +146,115 @@ public: PreservedPassIDs.count(PassID); } + /// \brief Test whether all passes are preserved. + /// + /// This is used primarily to optimize for the case of no changes which will + /// common in many scenarios. + bool areAllPreserved() const { + return PreservedPassIDs.count((void *)AllPassesID); + } + private: // Note that this must not be -1 or -2 as those are already used by the // SmallPtrSet. static const uintptr_t AllPassesID = (intptr_t)(-3); - bool areAllPreserved() const { - return PreservedPassIDs.count((void *)AllPassesID); - } - SmallPtrSet PreservedPassIDs; }; -/// \brief Implementation details of the pass manager interfaces. -namespace detail { - -/// \brief Template for the abstract base class used to dispatch -/// polymorphically over pass objects. -template struct PassConcept { - // Boiler plate necessary for the container of derived classes. - virtual ~PassConcept() {} - - /// \brief The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0; - - /// \brief Polymorphic method to access the name of a pass. - virtual StringRef name() = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c PassT has a run method -/// accepting an \c AnalysisManagerT. -template -class PassRunAcceptsAnalysisManager { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); +// Forward declare the analysis manager template. +template class AnalysisManager; -public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief A template wrapper used to implement the polymorphic API. +/// \brief Manages a sequence of passes over units of IR. /// -/// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT. It requires the pass to be a copyable object. When the -/// \c run method also accepts an \c AnalysisManagerT*, we pass it along. -template ::Value> -struct PassModel; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR, AM); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Abstract concept of an analysis result. +/// A pass manager contains a sequence of passes to run over units of IR. It is +/// itself a valid pass over that unit of IR, and when over some given IR will +/// run each pass in sequence. This is the primary and most basic building +/// block of a pass pipeline. /// -/// This concept is parameterized over the IR unit that this result pertains -/// to. -template struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() {} - - /// \brief Method to try and mark a result as invalid. - /// - /// When the outer analysis manager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// This method also receives a set of preserved analyses which can be used - /// to avoid invalidation because the pass which changed the underlying IR - /// took care to update or preserve the analysis result in some way. - /// - /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c ResultT provides an -/// \c invalidate member function. -template class ResultHasInvalidateMethod { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); - +/// If it is run with an \c AnalysisManager argument, it will propagate +/// that analysis manager to each pass it runs, as well as calling the analysis +/// manager's invalidation routine with the PreservedAnalyses of each pass it +/// runs. +template class PassManager { public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief Wrapper to model the analysis result concept. -/// -/// By default, this will implement the invalidate method with a trivial -/// implementation so that the actual analysis result doesn't need to provide -/// an invalidation handler. It is only selected when the invalidation handler -/// is not part of the ResultT's interface. -template ::Value> -struct AnalysisResultModel; - -/// \brief Specialization of \c AnalysisResultModel which provides the default -/// invalidate functionality. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model bases invalidation solely on being in the preserved set. - // - // FIXME: We should actually use two different concepts for analysis results - // rather than two different models, and avoid the indirect function call for - // ones that use the trivial behavior. - bool invalidate(IRUnitT, const PreservedAnalyses &PA) override { - return !PA.preserved(PassT::ID()); - } - - ResultT Result; -}; - -/// \brief Specialization of \c AnalysisResultModel which delegates invalidate -/// handling to \c ResultT. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + /// \brief Construct a pass manager. + /// + /// It can be passed a flag to get debug logging as the passes are run. + PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); + PassManager(PassManager &&Arg) + : Passes(std::move(Arg.Passes)), + DebugLogging(std::move(Arg.DebugLogging)) {} + PassManager &operator=(PassManager &&RHS) { + Passes = std::move(RHS.Passes); + DebugLogging = std::move(RHS.DebugLogging); return *this; } - /// \brief The model delegates to the \c ResultT method. - bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { - return Result.invalidate(IR, PA); - } + /// \brief Run all of the passes in this manager over the IR. + PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM = nullptr) { + PreservedAnalyses PA = PreservedAnalyses::all(); - ResultT Result; -}; + if (DebugLogging) + dbgs() << "Starting pass manager run.\n"; -/// \brief Abstract concept of an analysis pass. -/// -/// This concept is parameterized over the IR unit that it can run over and -/// produce an analysis result. -template -struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() {} - - /// \brief Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) = 0; -}; + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + if (DebugLogging) + dbgs() << "Running pass: " << Passes[Idx]->name() << "\n"; -/// \brief Wrapper to model the analysis pass concept. -/// -/// Can wrap any type which implements a suitable \c run method. The method -/// must accept the IRUnitT as an argument and produce an object which can be -/// wrapped in a \c AnalysisResultModel. -template ::Value> -struct AnalysisPassModel; - -/// \brief Specialization of \c AnalysisPassModel which passes an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) override { - return make_unique(Pass.run(IR, AM)); - } + PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); - PassT Pass; -}; + // If we have an active analysis manager at this level we want to ensure + // we update it as each pass runs and potentially invalidates analyses. + // We also update the preserved set of analyses based on what analyses we + // have already handled the invalidation for here and don't need to + // invalidate when finished. + if (AM) + PassPA = AM->invalidate(IR, std::move(PassPA)); -/// \brief Specialization of \c AnalysisPassModel which does not pass an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *) override { - return make_unique(Pass.run(IR)); - } - - PassT Pass; -}; + // Finally, we intersect the final preserved analyses to compute the + // aggregate preserved set for this pass manager. + PA.intersect(std::move(PassPA)); -} // End namespace detail + // FIXME: Historically, the pass managers all called the LLVM context's + // yield function here. We don't have a generic way to acquire the + // context and it isn't yet clear what the right pattern is for yielding + // in the new pass manager so it is currently omitted. + //IR.getContext().yield(); + } -class ModuleAnalysisManager; + if (DebugLogging) + dbgs() << "Finished pass manager run.\n"; -class ModulePassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModulePassManager() {} - ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - ModulePassManager &operator=(ModulePassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; + return PA; } - /// \brief Run all of the module passes in this module pass manager over - /// a module. - /// - /// This method should only be called for a single module as there is the - /// expectation that the lifetime of a pass is bounded to that of a module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr); - - template void addPass(ModulePassT Pass) { - Passes.emplace_back(new ModulePassModel(std::move(Pass))); + template void addPass(PassT Pass) { + typedef detail::PassModel PassModelT; + Passes.emplace_back(new PassModelT(std::move(Pass))); } - static StringRef name() { return "ModulePassManager"; } + static StringRef name() { return "PassManager"; } private: - // Pull in the concept type and model template specialized for modules. - typedef detail::PassConcept - ModulePassConcept; - template - struct ModulePassModel - : detail::PassModel { - ModulePassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; - - ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION; - ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION; + typedef detail::PassConcept PassConceptT; - std::vector> Passes; -}; + PassManager(const PassManager &) = delete; + PassManager &operator=(const PassManager &) = delete; -class FunctionAnalysisManager; + std::vector> Passes; -class FunctionPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionPassManager() {} - FunctionPassManager(FunctionPassManager &&Arg) - : Passes(std::move(Arg.Passes)) {} - FunctionPassManager &operator=(FunctionPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - template void addPass(FunctionPassT Pass) { - Passes.emplace_back(new FunctionPassModel(std::move(Pass))); - } - - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr); - - static StringRef name() { return "FunctionPassManager"; } + /// \brief Flag indicating whether we should do debug logging. + bool DebugLogging; +}; -private: - // Pull in the concept type and model template specialized for functions. - typedef detail::PassConcept - FunctionPassConcept; - template - struct FunctionPassModel - : detail::PassModel { - FunctionPassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; +/// \brief Convenience typedef for a pass manager over modules. +typedef PassManager ModulePassManager; - FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - FunctionPassManager & - operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - - std::vector> Passes; -}; +/// \brief Convenience typedef for a pass manager over functions. +typedef PassManager FunctionPassManager; namespace detail { @@ -556,19 +269,25 @@ namespace detail { /// - invalidateImpl /// /// The details of the call pattern are within. +/// +/// Note that there is also a generic analysis manager template which implements +/// the above required functions along with common datastructures used for +/// managing analyses. This base class is factored so that if you need to +/// customize the handling of a specific IR unit, you can do so without +/// replicating *all* of the boilerplate. template class AnalysisManagerBase { DerivedT *derived_this() { return static_cast(this); } const DerivedT *derived_this() const { return static_cast(this); } - AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + AnalysisManagerBase(const AnalysisManagerBase &) = delete; AnalysisManagerBase & - operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + operator=(const AnalysisManagerBase &) = delete; protected: typedef detail::AnalysisResultConcept ResultConceptT; - typedef detail::AnalysisPassConcept PassConceptT; + typedef detail::AnalysisPassConcept PassConceptT; // FIXME: Provide template aliases for the models when we're using C++11 in // a mode supporting them. @@ -588,7 +307,7 @@ public: /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - template typename PassT::Result &getResult(IRUnitT IR) { + template typename PassT::Result &getResult(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -605,7 +324,7 @@ public: /// /// \returns null if there is no cached result. template - typename PassT::Result *getCachedResult(IRUnitT IR) const { + typename PassT::Result *getCachedResult(IRUnitT &IR) const { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -627,25 +346,28 @@ public: template void registerPass(PassT Pass) { assert(!AnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - typedef detail::AnalysisPassModel PassModelT; + typedef detail::AnalysisPassModel PassModelT; AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass))); } /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. - template void invalidate(Module *M) { + template void invalidate(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), IR); } /// \brief Invalidate analyses cached for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and /// invalidate them unless they are preserved by the PreservedAnalyses set. - void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { - derived_this()->invalidateImpl(IR, PA); + /// We accept the PreservedAnalyses set by value and update it with each + /// analyis pass which has been successfully invalidated and thus can be + /// preserved going forward. The updated set is returned. + PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { + return derived_this()->invalidateImpl(IR, std::move(PA)); } protected: @@ -675,108 +397,153 @@ private: } // End namespace detail -/// \brief A module analysis pass manager with lazy running and caching of +/// \brief A generic analysis pass manager with lazy running and caching of /// results. -class ModuleAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleAnalysisManager() {} - ModuleAnalysisManager(ModuleAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {} - ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults); - return *this; - } - -private: - ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - ModuleAnalysisManager & - operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a module pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Module *M); - - /// \brief Get a cached module pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; - - /// \brief Invalidate a module pass result. - void invalidateImpl(void *PassID, Module *M); - - /// \brief Invalidate results across a module. - void invalidateImpl(Module *M, const PreservedAnalyses &PA); - - /// \brief Map type from module analysis pass ID to pass result concept - /// pointer. - typedef DenseMap>> - ModuleAnalysisResultMapT; - - /// \brief Cache of computed module analysis results for this module. - ModuleAnalysisResultMapT ModuleAnalysisResults; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class FunctionAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase - BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; +/// +/// This analysis manager can be used for any IR unit where the address of the +/// IR unit sufficies as its identity. It manages the cache for a unit of IR via +/// the address of each unit of IR cached. +template +class AnalysisManager + : public detail::AnalysisManagerBase, IRUnitT> { + friend class detail::AnalysisManagerBase, IRUnitT>; + typedef detail::AnalysisManagerBase, IRUnitT> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; public: // Most public APIs are inherited from the CRTP base class. + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - FunctionAnalysisManager() {} - FunctionAnalysisManager(FunctionAnalysisManager &&Arg) + AnalysisManager(AnalysisManager &&Arg) : BaseT(std::move(static_cast(Arg))), - FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {} - FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) { + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} + AnalysisManager &operator=(AnalysisManager &&RHS) { BaseT::operator=(std::move(static_cast(RHS))); - FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults); + AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); return *this; } /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; + bool empty() const { + assert(AnalysisResults.empty() == AnalysisResultLists.empty() && + "The storage and index of analysis results disagree on how many " + "there are!"); + return AnalysisResults.empty(); + } - /// \brief Clear the function analysis result cache. + /// \brief Clear the analysis result cache. /// - /// This routine allows cleaning up when the set of functions itself has + /// This routine allows cleaning up when the set of IR units itself has /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); + /// invalidate it directly. Notably, this does *not* call invalidate functions + /// as there is nothing to be done for them. + void clear() { + AnalysisResults.clear(); + AnalysisResultLists.clear(); + } private: - FunctionAnalysisManager(const FunctionAnalysisManager &) - LLVM_DELETED_FUNCTION; - FunctionAnalysisManager & - operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) = delete; + AnalysisManager &operator=(const AnalysisManager &) = delete; + + /// \brief Get an analysis result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI; + bool Inserted; + std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( + std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator())); + + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. + if (Inserted) { + auto &P = this->lookupPass(PassID); + if (DebugLogging) + dbgs() << "Running analysis: " << P.name() << "\n"; + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; + ResultList.emplace_back(PassID, P.run(IR, this)); + RI->second = std::prev(ResultList.end()); + } - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Function *F); + return *RI->second->second; + } - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; + /// \brief Get a cached analysis result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const { + typename AnalysisResultMapT::const_iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; + } /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, Function *F); + void invalidateImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + if (RI == AnalysisResults.end()) + return; + + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + AnalysisResultLists[&IR].erase(RI->second); + AnalysisResults.erase(RI); + } /// \brief Invalidate the results for a function.. - void invalidateImpl(Function *F, const PreservedAnalyses &PA); + PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { + // Short circuit for a common case of all analyses being preserved. + if (PA.areAllPreserved()) + return std::move(PA); + + if (DebugLogging) + dbgs() << "Invalidating all non-preserved analyses for: " + << IR.getName() << "\n"; + + // Clear all the invalidated results associated specifically with this + // function. + SmallVector InvalidatedPassIDs; + AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; + for (typename AnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) { + void *PassID = I->first; + + // Pass the invalidation down to the pass itself to see if it thinks it is + // necessary. The analysis pass can return false if no action on the part + // of the analysis manager is required for this invalidation event. + if (I->second->invalidate(IR, PA)) { + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + + InvalidatedPassIDs.push_back(I->first); + I = ResultsList.erase(I); + } else { + ++I; + } + + // After handling each pass, we mark it as preserved. Once we've + // invalidated any stale results, the rest of the system is allowed to + // start preserving this analysis again. + PA.preserve(PassID); + } + while (!InvalidatedPassIDs.empty()) + AnalysisResults.erase( + std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR)); + if (ResultsList.empty()) + AnalysisResultLists.erase(&IR); + + return std::move(PA); + } /// \brief List of function analysis pass IDs and associated concept pointers. /// @@ -784,30 +551,37 @@ private: /// erases. Provides both the pass ID and concept pointer such that it is /// half of a bijection and provides storage for the actual result concept. typedef std::list>>> - FunctionAnalysisResultListT; + void *, std::unique_ptr>>> + AnalysisResultListT; /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - FunctionAnalysisResultListMapT; + typedef DenseMap AnalysisResultListMapT; /// \brief Map from function to a list of function analysis results. /// /// Provides linear time removal of all analysis results for a function and /// the ultimate storage for a particular cached analysis result. - FunctionAnalysisResultListMapT FunctionAnalysisResultLists; + AnalysisResultListMapT AnalysisResultLists; /// \brief Map type from a pair of analysis ID and function pointer to an /// iterator into a particular result list. - typedef DenseMap, - FunctionAnalysisResultListT::iterator> - FunctionAnalysisResultMapT; + typedef DenseMap, + typename AnalysisResultListT::iterator> AnalysisResultMapT; /// \brief Map from an analysis ID and function to a particular cached /// analysis result. - FunctionAnalysisResultMapT FunctionAnalysisResults; + AnalysisResultMapT AnalysisResults; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; }; +/// \brief Convenience typedef for the Module analysis manager. +typedef AnalysisManager ModuleAnalysisManager; + +/// \brief Convenience typedef for the Function analysis manager. +typedef AnalysisManager FunctionAnalysisManager; + /// \brief A module analysis which acts as a proxy for a function analysis /// manager. /// @@ -822,6 +596,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; } + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -846,7 +622,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -884,7 +660,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -920,7 +696,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -928,6 +704,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; } + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC @@ -946,7 +724,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(Function *) { return Result(*MAM); } + Result run(Function &) { return Result(*MAM); } private: static char PassID; @@ -962,6 +740,20 @@ private: /// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function /// pass over the module to enable a \c FunctionAnalysisManager to be used /// within this run safely. +/// +/// Function passes run within this adaptor can rely on having exclusive access +/// to the function they are run over. They should not read or modify any other +/// functions! Other threads or systems may be manipulating other functions in +/// the module, and so their state should never be relied on. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. +/// +/// Function passes can also read the module containing the function, but they +/// should not modify that module outside of the use lists of various globals. +/// For example, a function pass is not permitted to add functions to the +/// module. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. template class ModuleToFunctionPassAdaptor { public: explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) @@ -972,7 +764,8 @@ public: : Pass(Arg.Pass) {} ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) { + friend void swap(ModuleToFunctionPassAdaptor &LHS, + ModuleToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -982,21 +775,26 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(I, FAM); + for (Function &F : M) { + if (F.isDeclaration()) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so - // directly handle the function analysis manager's invalidation here. + // directly handle the function analysis manager's invalidation here and + // update our preserved set to reflect that these have already been + // handled. if (FAM) - FAM->invalidate(I, PassPA); + PassPA = FAM->invalidate(F, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -1025,6 +823,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(ModuleToFunctionPassAdaptor(std::move(Pass))); } +/// \brief A template utility pass to force an analysis result to be available. +/// +/// This is a no-op pass which simply forces a specific analysis pass's result +/// to be available when it is run. +template struct RequireAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + (void)AM->template getResult(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "RequireAnalysisPass"; } +}; + +/// \brief A template utility pass to force an analysis result to be +/// invalidated. +/// +/// This is a no-op pass which simply forces a specific analysis result to be +/// invalidated when it is run. +template struct InvalidateAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + // We have to directly invalidate the analysis result as we can't + // enumerate all other analyses and use the preserved set to control it. + (void)AM->template invalidate(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "InvalidateAnalysisPass"; } +}; + +/// \brief A utility pass that does nothing but preserves no analyses. +/// +/// As a consequence fo not preserving any analyses, this pass will force all +/// analysis passes to be re-run to produce fresh results if any are needed. +struct InvalidateAllAnalysesPass { + /// \brief Run this pass over some unit of IR. + template PreservedAnalyses run(IRUnitT &Arg) { + return PreservedAnalyses::none(); + } + + static StringRef name() { return "InvalidateAllAnalysesPass"; } +}; + } #endif diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h new file mode 100644 index 0000000..297f5f4 --- /dev/null +++ b/include/llvm/IR/PassManagerInternal.h @@ -0,0 +1,349 @@ +//===- PassManager internal APIs and implementation details -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides internal APIs and implementation details used by the +/// pass management interfaces exposed in PassManager.h. To understand more +/// context of why these particular interfaces are needed, see that header +/// file. None of these APIs should be used elsewhere. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSMANAGERINTERNAL_H +#define LLVM_IR_PASSMANAGERINTERNAL_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +template class AnalysisManager; +class PreservedAnalyses; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + + /// \brief The polymorphic API which runs the pass over a given IR entity. + /// + /// Note that actual pass object can omit the analysis manager argument if + /// desired. Also that the analysis manager may be null if there is no + /// analysis manager in the pass pipeline. + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c PassT has a run method +/// accepting an \c AnalysisManager. +template +class PassRunAcceptsAnalysisManager { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template *)> + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method accepting +/// an \c IRUnitT. It requires the pass to be a copyable object. When the +/// \c run method also accepts an \c AnalysisManager*, we pass it +/// along. +template ::Value> +struct PassModel; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR, AM); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Abstract concept of an analysis result. +/// +/// This concept is parameterized over the IR unit that this result pertains +/// to. +template struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer analysis manager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// This method also receives a set of preserved analyses which can be used + /// to avoid invalidation because the pass which changed the underlying IR + /// took care to update or preserve the analysis result in some way. + /// + /// \returns true if the result is indeed invalid (the default). + virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// \c invalidate member function. +template class ResultHasInvalidateMethod { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief Wrapper to model the analysis result concept. +/// +/// By default, this will implement the invalidate method with a trivial +/// implementation so that the actual analysis result doesn't need to provide +/// an invalidation handler. It is only selected when the invalidation handler +/// is not part of the ResultT's interface. +template ::Value> +struct AnalysisResultModel; + +/// \brief Specialization of \c AnalysisResultModel which provides the default +/// invalidate functionality. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model bases invalidation solely on being in the preserved set. + // + // FIXME: We should actually use two different concepts for analysis results + // rather than two different models, and avoid the indirect function call for + // ones that use the trivial behavior. + bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override { + return !PA.preserved(PassT::ID()); + } + + ResultT Result; +}; + +/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// handling to \c ResultT. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model delegates to the \c ResultT method. + bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override { + return Result.invalidate(IR, PA); + } + + ResultT Result; +}; + +/// \brief Abstract concept of an analysis pass. +/// +/// This concept is parameterized over the IR unit that it can run over and +/// produce an analysis result. +template struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + + /// \brief Method to run this analysis over a unit of IR. + /// \returns A unique_ptr to the analysis result object to be queried by + /// users. + virtual std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief Wrapper to model the analysis pass concept. +/// +/// Can wrap any type which implements a suitable \c run method. The method +/// must accept the IRUnitT as an argument and produce an object which can be +/// wrapped in a \c AnalysisResultModel. +template ::Value> +struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) override { + return make_unique(Pass.run(IR, AM)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *) override { + return make_unique(Pass.run(IR)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +} // End namespace detail +} + +#endif diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 4783062..f94e105 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -38,55 +38,58 @@ namespace llvm { namespace PatternMatch { -template -bool match(Val *V, const Pattern &P) { - return const_cast(P).match(V); +template bool match(Val *V, const Pattern &P) { + return const_cast(P).match(V); } - -template -struct OneUse_match { +template struct OneUse_match { SubPattern_t SubPattern; OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); } }; -template -inline OneUse_match m_OneUse(const T &SubPattern) { return SubPattern; } - +template inline OneUse_match m_OneUse(const T &SubPattern) { + return SubPattern; +} -template -struct class_match { - template - bool match(ITy *V) { return isa(V); } +template struct class_match { + template bool match(ITy *V) { return isa(V); } }; -/// m_Value() - Match an arbitrary value and ignore it. +/// \brief Match an arbitrary value and ignore it. inline class_match m_Value() { return class_match(); } -/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. + +/// \brief Match an arbitrary binary operation and ignore it. +inline class_match m_BinOp() { + return class_match(); +} + +/// \brief Matches any compare instruction and ignore it. +inline class_match m_Cmp() { return class_match(); } + +/// \brief Match an arbitrary ConstantInt and ignore it. inline class_match m_ConstantInt() { return class_match(); } -/// m_Undef() - Match an arbitrary undef constant. + +/// \brief Match an arbitrary undef constant. inline class_match m_Undef() { return class_match(); } +/// \brief Match an arbitrary Constant and ignore it. inline class_match m_Constant() { return class_match(); } /// Matching combinators -template -struct match_combine_or { +template struct match_combine_or { LTy L; RTy R; - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) return true; if (R.match(V)) @@ -95,15 +98,13 @@ struct match_combine_or { } }; -template -struct match_combine_and { +template struct match_combine_and { LTy L; RTy R; - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) if (R.match(V)) return true; @@ -112,46 +113,44 @@ struct match_combine_and { }; /// Combine two pattern matchers matching L || R -template +template inline match_combine_or m_CombineOr(const LTy &L, const RTy &R) { return match_combine_or(L, R); } /// Combine two pattern matchers matching L && R -template +template inline match_combine_and m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and(L, R); } struct match_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNullValue(); return false; } }; -/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } struct match_neg_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNegativeZeroValue(); return false; } }; -/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero but not positive /// zero inline match_neg_zero m_NegZero() { return match_neg_zero(); } -/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// \brief - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero and positive zero inline match_combine_or m_AnyZero() { @@ -161,16 +160,14 @@ inline match_combine_or m_AnyZero() { struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (ConstantInt *CI = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CI = dyn_cast(V)) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) { + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) { Res = &CI->getValue(); return true; } @@ -178,16 +175,13 @@ struct apint_match { } }; -/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// \brief Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - -template -struct constantint_match { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) { +template struct constantint_match { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) return CIV == static_cast(Val); @@ -200,45 +194,39 @@ struct constantint_match { } }; -/// m_ConstantInt - Match a ConstantInt with a specific value. -template -inline constantint_match m_ConstantInt() { +/// \brief Match a ConstantInt with a specific value. +template inline constantint_match m_ConstantInt() { return constantint_match(); } -/// cst_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate. -template -struct cst_pred_ty : public Predicate { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate. +template struct cst_pred_ty : public Predicate { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) return this->isValue(CI->getValue()); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (const ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (const auto *CI = dyn_cast_or_null(C->getSplatValue())) return this->isValue(CI->getValue()); return false; } }; -/// api_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate, and bind them to an APInt. -template -struct api_pred_ty : public Predicate { +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate, and bind them to an APInt. +template struct api_pred_ty : public Predicate { const APInt *&Res; api_pred_ty(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; @@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate { } }; - struct is_one { bool isValue(const APInt &C) { return C == 1; } }; -/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +/// \brief Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty m_One() { return cst_pred_ty(); } inline api_pred_ty m_One(const APInt *&V) { return V; } @@ -261,34 +248,43 @@ struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; -/// m_AllOnes() - Match an integer or vector with all bits set to true. -inline cst_pred_ty m_AllOnes() {return cst_pred_ty();} +/// \brief Match an integer or vector with all bits set to true. +inline cst_pred_ty m_AllOnes() { + return cst_pred_ty(); +} inline api_pred_ty m_AllOnes(const APInt *&V) { return V; } struct is_sign_bit { bool isValue(const APInt &C) { return C.isSignBit(); } }; -/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. -inline cst_pred_ty m_SignBit() {return cst_pred_ty();} +/// \brief Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty m_SignBit() { + return cst_pred_ty(); +} inline api_pred_ty m_SignBit(const APInt *&V) { return V; } struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; -/// m_Power2() - Match an integer or vector power of 2. +/// \brief Match an integer or vector power of 2. inline cst_pred_ty m_Power2() { return cst_pred_ty(); } inline api_pred_ty m_Power2(const APInt *&V) { return V; } -template -struct bind_ty { +struct is_maxsignedvalue { + bool isValue(const APInt &C) { return C.isMaxSignedValue(); } +}; + +inline cst_pred_ty m_MaxSignedValue() { return cst_pred_ty(); } +inline api_pred_ty m_MaxSignedValue(const APInt *&V) { return V; } + +template struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} - template - bool match(ITy *V) { - if (Class *CV = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CV = dyn_cast(V)) { VR = CV; return true; } @@ -296,64 +292,62 @@ struct bind_ty { } }; -/// m_Value - Match a value, capturing it if we match. +/// \brief Match a value, capturing it if we match. inline bind_ty m_Value(Value *&V) { return V; } -/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +/// \brief Match a binary operator, capturing it if we match. +inline bind_ty m_BinOp(BinaryOperator *&I) { return I; } + +/// \brief Match a ConstantInt, capturing the value if we match. inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } -/// m_Constant - Match a Constant, capturing the value if we match. +/// \brief Match a Constant, capturing the value if we match. inline bind_ty m_Constant(Constant *&C) { return C; } -/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +/// \brief Match a ConstantFP, capturing the value if we match. inline bind_ty m_ConstantFP(ConstantFP *&C) { return C; } -/// specificval_ty - Match a specified Value*. +/// \brief Match a specified Value*. struct specificval_ty { const Value *Val; specificval_ty(const Value *V) : Val(V) {} - template - bool match(ITy *V) { - return V == Val; - } + template bool match(ITy *V) { return V == Val; } }; -/// m_Specific - Match if we have a specific specified value. +/// \brief Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } -/// Match a specified floating point value or vector of all elements of that -/// value. +/// \brief Match a specified floating point value or vector of all elements of +/// that value. struct specific_fpval { double Val; specific_fpval(double V) : Val(V) {} - template - bool match(ITy *V) { - if (const ConstantFP *CFP = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CFP = dyn_cast(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantFP *CFP = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CFP = dyn_cast_or_null(C->getSplatValue())) return CFP->isExactlyValue(Val); return false; } }; -/// Match a specific floating point value or vector with all elements equal to -/// the value. +/// \brief Match a specific floating point value or vector with all elements +/// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } -/// Match a float 1.0 or vector with all elements equal to 1.0. +/// \brief Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - template - bool match(ITy *V) { - if (ConstantInt *CV = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CV = dyn_cast(V)) if (CV->getBitWidth() <= 64) { VR = CV->getZExtValue(); return true; @@ -362,14 +356,14 @@ struct bind_const_intval_ty { } }; -/// Match a specified integer value or vector of all elements of that value. +/// \brief Match a specified integer value or vector of all elements of that +// value. struct specific_intval { uint64_t Val; specific_intval(uint64_t V) : Val(V) {} - template - bool match(ITy *V) { - ConstantInt *CI = dyn_cast(V); + template bool match(ITy *V) { + const auto *CI = dyn_cast(V); if (!CI && V->getType()->isVectorTy()) if (const auto *C = dyn_cast(V)) CI = dyn_cast_or_null(C->getSplatValue()); @@ -381,156 +375,177 @@ struct specific_intval { } }; -/// Match a specific integer value or vector with all elements equal to the -/// value. +/// \brief Match a specific integer value or vector with all elements equal to +/// the value. inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); } -/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not -/// match ConstantInts wider than 64-bits. +/// \brief Match a ConstantInt and bind to its value. This does not match +/// ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } //===----------------------------------------------------------------------===// +// Matcher for any binary operator. +// +template struct AnyBinaryOp_match { + LHS_t L; + RHS_t R; + + AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + return false; + } +}; + +template +inline AnyBinaryOp_match m_BinOp(const LHS &L, const RHS &R) { + return AnyBinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// // Matchers for specific binary operators. // -template +template struct BinaryOp_match { LHS_t L; RHS_t R; BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -template -inline BinaryOp_match -m_Add(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Add(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FAdd(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FAdd(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Sub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Sub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FSub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FSub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Mul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Mul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FMul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FMul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_UDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_UDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_URem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_URem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_And(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_And(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Or(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Or(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Xor(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Xor(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Shl(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Shl(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_LShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_LShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_AShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_AShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template +template struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; - OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) + : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (OverflowingBinaryOperator *Op = dyn_cast(V)) { + template bool match(OpTy *V) { + if (auto *Op = dyn_cast(V)) { if (Op->getOpcode() != Opcode) return false; if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && @@ -614,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // -template +template struct BinOp2_match { LHS_t L; RHS_t R; BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opc1 || V->getValueID() == Value::InstructionVal + Opc2) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -/// m_Shr - Matches LShr or AShr. -template +/// \brief Matches LShr or AShr. +template inline BinOp2_match m_Shr(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_LogicalShift - Matches LShr or Shl. -template +/// \brief Matches LShr or Shl. +template inline BinOp2_match m_LogicalShift(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_IDiv - Matches UDiv and SDiv. -template +/// \brief Matches UDiv and SDiv. +template inline BinOp2_match m_IDiv(const LHS &L, const RHS &R) { return BinOp2_match(L, R); @@ -659,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches exact binary ops. // -template -struct Exact_match { +template struct Exact_match { SubPattern_t SubPattern; Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (PossiblyExactOperator *PEO = dyn_cast(V)) return PEO->isExact() && SubPattern.match(V); return false; } }; -template -inline Exact_match m_Exact(const T &SubPattern) { return SubPattern; } +template inline Exact_match m_Exact(const T &SubPattern) { + return SubPattern; +} //===----------------------------------------------------------------------===// // Matchers for CmpInst classes // -template +template struct CmpClass_match { PredicateTy &Predicate; LHS_t L; RHS_t R; CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} + : Predicate(Pred), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (Class *I = dyn_cast(V)) if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); @@ -700,123 +712,114 @@ struct CmpClass_match { } }; -template +template +inline CmpClass_match +m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +template inline CmpClass_match m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } -template +template inline CmpClass_match m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } //===----------------------------------------------------------------------===// // Matchers for SelectInst classes // -template +template struct SelectClass_match { Cond_t C; LHS_t L; RHS_t R; - SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, - const RHS_t &RHS) - : C(Cond), L(LHS), R(RHS) {} + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (SelectInst *I = dyn_cast(V)) - return C.match(I->getOperand(0)) && - L.match(I->getOperand(1)) && + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) && R.match(I->getOperand(2)); return false; } }; -template -inline SelectClass_match -m_Select(const Cond &C, const LHS &L, const RHS &R) { +template +inline SelectClass_match m_Select(const Cond &C, const LHS &L, + const RHS &R) { return SelectClass_match(C, L, R); } -/// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template -inline SelectClass_match, constantint_match > +/// \brief This matches a select of two constants, e.g.: +/// m_SelectCst<-1, 0>(m_Value(V)) +template +inline SelectClass_match, constantint_match> m_SelectCst(const Cond &C) { return m_Select(C, m_ConstantInt(), m_ConstantInt()); } - //===----------------------------------------------------------------------===// // Matchers for CastInst classes // -template -struct CastClass_match { +template struct CastClass_match { Op_t Op; CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; } }; -/// m_BitCast -template -inline CastClass_match -m_BitCast(const OpTy &Op) { +/// \brief Matches BitCast. +template +inline CastClass_match m_BitCast(const OpTy &Op) { return CastClass_match(Op); } -/// m_PtrToInt -template -inline CastClass_match -m_PtrToInt(const OpTy &Op) { +/// \brief Matches PtrToInt. +template +inline CastClass_match m_PtrToInt(const OpTy &Op) { return CastClass_match(Op); } -/// m_Trunc -template -inline CastClass_match -m_Trunc(const OpTy &Op) { +/// \brief Matches Trunc. +template +inline CastClass_match m_Trunc(const OpTy &Op) { return CastClass_match(Op); } -/// m_SExt -template -inline CastClass_match -m_SExt(const OpTy &Op) { +/// \brief Matches SExt. +template +inline CastClass_match m_SExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_ZExt -template -inline CastClass_match -m_ZExt(const OpTy &Op) { +/// \brief Matches ZExt. +template +inline CastClass_match m_ZExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_UIToFP -template -inline CastClass_match -m_UIToFP(const OpTy &Op) { +/// \brief Matches UIToFP. +template +inline CastClass_match m_UIToFP(const OpTy &Op) { return CastClass_match(Op); } -/// m_SIToFP -template -inline CastClass_match -m_SIToFP(const OpTy &Op) { +/// \brief Matches SIToFP. +template +inline CastClass_match m_SIToFP(const OpTy &Op) { return CastClass_match(Op); } @@ -824,46 +827,41 @@ m_SIToFP(const OpTy &Op) { // Matchers for unary operators // -template -struct not_match { +template struct not_match { LHS_t L; not_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Xor) return matchIfNot(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNot(Value *LHS, Value *RHS) { return (isa(RHS) || isa(RHS) || // FIXME: Remove CV. isa(RHS)) && - cast(RHS)->isAllOnesValue() && - L.match(LHS); + cast(RHS)->isAllOnesValue() && L.match(LHS); } }; -template -inline not_match m_Not(const LHS &L) { return L; } +template inline not_match m_Not(const LHS &L) { return L; } - -template -struct neg_match { +template struct neg_match { LHS_t L; neg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Sub) return matchIfNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNeg(Value *LHS, Value *RHS) { return ((isa(LHS) && cast(LHS)->isZero()) || @@ -872,36 +870,33 @@ private: } }; -/// m_Neg - Match an integer negate. -template -inline neg_match m_Neg(const LHS &L) { return L; } - +/// \brief Match an integer negate. +template inline neg_match m_Neg(const LHS &L) { return L; } -template -struct fneg_match { +template struct fneg_match { LHS_t L; fneg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::FSub) return matchIfFNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfFNeg(Value *LHS, Value *RHS) { - if (ConstantFP *C = dyn_cast(LHS)) + if (const auto *C = dyn_cast(LHS)) return C->isNegativeZeroValue() && L.match(RHS); return false; } }; -/// m_FNeg - Match a floating point negate. -template -inline fneg_match m_FNeg(const LHS &L) { return L; } - +/// \brief Match a floating point negate. +template inline fneg_match m_FNeg(const LHS &L) { + return L; +} //===----------------------------------------------------------------------===// // Matchers for control flow. @@ -909,13 +904,10 @@ inline fneg_match m_FNeg(const LHS &L) { return L; } struct br_match { BasicBlock *&Succ; - br_match(BasicBlock *&Succ) - : Succ(Succ) { - } + br_match(BasicBlock *&Succ) : Succ(Succ) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isUnconditional()) { Succ = BI->getSuccessor(0); return true; @@ -926,17 +918,14 @@ struct br_match { inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } -template -struct brc_match { +template struct brc_match { Cond_t Cond; BasicBlock *&T, *&F; brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) - : Cond(C), T(t), F(f) { - } + : Cond(C), T(t), F(f) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isConditional() && Cond.match(BI->getCondition())) { T = BI->getSuccessor(0); F = BI->getSuccessor(1); @@ -946,31 +935,28 @@ struct brc_match { } }; -template +template inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { return brc_match(C, T, F); } - //===----------------------------------------------------------------------===// // Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). // -template +template struct MaxMin_match { LHS_t L; RHS_t R; - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} + MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - SelectInst *SI = dyn_cast(V); + auto *SI = dyn_cast(V); if (!SI) return false; - CmpInst_t *Cmp = dyn_cast(SI->getCondition()); + auto *Cmp = dyn_cast(SI->getCondition()); if (!Cmp) return false; // At this point we have a select conditioned on a comparison. Check that @@ -982,8 +968,8 @@ struct MaxMin_match { if ((TrueVal != LHS || FalseVal != RHS) && (TrueVal != RHS || FalseVal != LHS)) return false; - typename CmpInst_t::Predicate Pred = LHS == TrueVal ? - Cmp->getPredicate() : Cmp->getSwappedPredicate(); + typename CmpInst_t::Predicate Pred = + LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate(); // Does "(x pred y) ? x : y" represent the desired max/min operation? if (!Pred_t::match(Pred)) return false; @@ -992,83 +978,83 @@ struct MaxMin_match { } }; -/// smax_pred_ty - Helper class for identifying signed max predicates. +/// \brief Helper class for identifying signed max predicates. struct smax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; } }; -/// smin_pred_ty - Helper class for identifying signed min predicates. +/// \brief Helper class for identifying signed min predicates. struct smin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; } }; -/// umax_pred_ty - Helper class for identifying unsigned max predicates. +/// \brief Helper class for identifying unsigned max predicates. struct umax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; } }; -/// umin_pred_ty - Helper class for identifying unsigned min predicates. +/// \brief Helper class for identifying unsigned min predicates. struct umin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; } }; -/// ofmax_pred_ty - Helper class for identifying ordered max predicates. +/// \brief Helper class for identifying ordered max predicates. struct ofmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; } }; -/// ofmin_pred_ty - Helper class for identifying ordered min predicates. +/// \brief Helper class for identifying ordered min predicates. struct ofmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; } }; -/// ufmax_pred_ty - Helper class for identifying unordered max predicates. +/// \brief Helper class for identifying unordered max predicates. struct ufmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; } }; -/// ufmin_pred_ty - Helper class for identifying unordered min predicates. +/// \brief Helper class for identifying unordered min predicates. struct ufmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; } }; -template -inline MaxMin_match -m_SMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_SMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1081,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMax(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1096,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMin(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1111,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match(L, R); @@ -1126,40 +1112,37 @@ m_UnordFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMin(const LHS &L, const RHS &R) { return MaxMin_match(L, R); } -template -struct Argument_match { +template struct Argument_match { unsigned OpI; Opnd_t Val; - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { CallSite CS(V); return CS.isCall() && Val.match(CS.getArgument(OpI)); } }; -/// Match an argument -template +/// \brief Match an argument. +template inline Argument_match m_Argument(const Opnd_t &Op) { return Argument_match(OpI, Op); } -/// Intrinsic matchers. +/// \brief Intrinsic matchers. struct IntrinsicID_match { unsigned ID; - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } + IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - template - bool match(OpTy *V) { - if (const CallInst *CI = dyn_cast(V)) - if (const Function *F = CI->getCalledFunction()) + template bool match(OpTy *V) { + if (const auto *CI = dyn_cast(V)) + if (const auto *F = CI->getCalledFunction()) return F->getIntrinsicID() == ID; return false; } @@ -1172,73 +1155,71 @@ struct IntrinsicID_match { template struct m_Intrinsic_Ty; -template -struct m_Intrinsic_Ty { - typedef match_combine_and > Ty; + typename T9 = void, typename T10 = void> +struct m_Intrinsic_Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and> Ty; }; -template -struct m_Intrinsic_Ty { - typedef match_combine_and::Ty, - Argument_match > Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and::Ty, Argument_match> + Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; -/// Match intrinsic calls like this: -/// m_Intrinsic(m_Value(X)) -template -inline IntrinsicID_match -m_Intrinsic() { return IntrinsicID_match(IntrID); } +/// \brief Match intrinsic calls like this: +/// m_Intrinsic(m_Value(X)) +template inline IntrinsicID_match m_Intrinsic() { + return IntrinsicID_match(IntrID); +} -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0) { return m_CombineAnd(m_Intrinsic(), m_Argument<0>(Op0)); } -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, + const T1 &Op1) { return m_CombineAnd(m_Intrinsic(Op0), m_Argument<1>(Op1)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { return m_CombineAnd(m_Intrinsic(Op0, Op1), m_Argument<2>(Op2)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2), m_Argument<3>(Op3)); } -// Helper intrinsic matching specializations -template -inline typename m_Intrinsic_Ty::Ty -m_BSwap(const Opnd0 &Op0) { +// Helper intrinsic matching specializations. +template +inline typename m_Intrinsic_Ty::Ty m_BSwap(const Opnd0 &Op0) { return m_Intrinsic(Op0); } -template -inline typename m_Intrinsic_Ty::Ty -m_FMin(const Opnd0 &Op0, const Opnd1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_FMin(const Opnd0 &Op0, + const Opnd1 &Op1) { return m_Intrinsic(Op0, Op1); } -template -inline typename m_Intrinsic_Ty::Ty -m_FMax(const Opnd0 &Op0, const Opnd1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_FMax(const Opnd0 &Op0, + const Opnd1 &Op1) { return m_Intrinsic(Op0, Op1); } diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h new file mode 100644 index 0000000..38720ed --- /dev/null +++ b/include/llvm/IR/Statepoint.h @@ -0,0 +1,298 @@ +//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions and a wrapper class analogous to +// CallSite for accessing the fields of gc.statepoint, gc.relocate, and +// gc.result intrinsics +// +//===----------------------------------------------------------------------===// + +#ifndef __LLVM_IR_STATEPOINT_H +#define __LLVM_IR_STATEPOINT_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class GCRelocateOperands; +class ImmutableStatepoint; + +bool isStatepoint(const ImmutableCallSite &CS); +bool isStatepoint(const Value *inst); +bool isStatepoint(const Value &inst); + +bool isGCRelocate(const Value *inst); +bool isGCRelocate(const ImmutableCallSite &CS); + +bool isGCResult(const Value *inst); +bool isGCResult(const ImmutableCallSite &CS); + +/// Analogous to CallSiteBase, this provides most of the actual +/// functionality for Statepoint and ImmutableStatepoint. It is +/// templatized to allow easily specializing of const and non-const +/// concrete subtypes. This is structured analogous to CallSite +/// rather than the IntrinsicInst.h helpers since we want to support +/// invokable statepoints in the near future. +/// TODO: This does not currently allow the if(Statepoint S = ...) +/// idiom used with CallSites. Consider refactoring to support. +template +class StatepointBase { + CallSiteTy StatepointCS; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + + protected: + explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { + assert(isStatepoint(I)); + } + explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { + assert(isStatepoint(CS)); + } + + public: + typedef typename CallSiteTy::arg_iterator arg_iterator; + + /// Return the underlying CallSite. + CallSiteTy getCallSite() { + return StatepointCS; + } + + /// Return the value actually being called or invoked. + ValueTy *actualCallee() { + return StatepointCS.getArgument(0); + } + /// Number of arguments to be passed to the actual callee. + int numCallArgs() { + return cast(StatepointCS.getArgument(1))->getZExtValue(); + } + /// Number of additional arguments excluding those intended + /// for garbage collection. + int numTotalVMSArgs() { + return cast(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + } + + typename CallSiteTy::arg_iterator call_args_begin() { + // 3 = callTarget, #callArgs, flag + int Offset = 3; + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + typename CallSiteTy::arg_iterator call_args_end() { + int Offset = 3 + numCallArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for call arguments + iterator_range call_args() { + return iterator_range(call_args_begin(), call_args_end()); + } + + typename CallSiteTy::arg_iterator vm_state_begin() { + return call_args_end(); + } + typename CallSiteTy::arg_iterator vm_state_end() { + int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for vm state arguments + iterator_range vm_state_args() { + return iterator_range(vm_state_begin(), vm_state_end()); + } + + typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { + // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, + // 1st_#stack, 1st_#local, 1st_#monitor + return vm_state_begin() + 6; + } + + typename CallSiteTy::arg_iterator gc_args_begin() { + return vm_state_end(); + } + typename CallSiteTy::arg_iterator gc_args_end() { + return StatepointCS.arg_end(); + } + + /// range adapter for gc arguments + iterator_range gc_args() { + return iterator_range(gc_args_begin(), gc_args_end()); + } + + /// Get list of all gc reloactes linked to this statepoint + /// May contain several relocations for the same base/derived pair. + /// For example this could happen due to relocations on unwinding + /// path of invoke. + std::vector getRelocates(ImmutableStatepoint &IS); + +#ifndef NDEBUG + /// Asserts if this statepoint is malformed. Common cases for failure + /// include incorrect length prefixes for variable length sections or + /// illegal values for parameters. + void verify() { + assert(numCallArgs() >= 0 && + "number of arguments to actually callee can't be negative"); + + // The internal asserts in the iterator accessors do the rest. + (void)call_args_begin(); + (void)call_args_end(); + (void)vm_state_begin(); + (void)vm_state_end(); + (void)gc_args_begin(); + (void)gc_args_end(); + } +#endif +}; + +/// A specialization of it's base class for read only access +/// to a gc.statepoint. +class ImmutableStatepoint + : public StatepointBase { + typedef StatepointBase + Base; + +public: + explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} + explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} +}; + +/// A specialization of it's base class for read-write access +/// to a gc.statepoint. +class Statepoint : public StatepointBase { + typedef StatepointBase Base; + +public: + explicit Statepoint(Instruction *I) : Base(I) {} + explicit Statepoint(CallSite CS) : Base(CS) {} +}; + +/// Wraps a call to a gc.relocate and provides access to it's operands. +/// TODO: This should likely be refactored to resememble the wrappers in +/// InstrinsicInst.h. +class GCRelocateOperands { + ImmutableCallSite RelocateCS; + + public: + GCRelocateOperands(const User* U) : RelocateCS(U) { + assert(isGCRelocate(U)); + } + GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { + assert(isGCRelocate(inst)); + } + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { + assert(isGCRelocate(CS)); + } + + /// Return true if this relocate is tied to the invoke statepoint. + /// This includes relocates which are on the unwinding path. + bool isTiedToInvoke() const { + const Value *Token = RelocateCS.getArgument(0); + + return isa(Token) || + isa(Token); + } + + /// Get enclosed relocate intrinsic + ImmutableCallSite getUnderlyingCallSite() { + return RelocateCS; + } + + /// The statepoint with which this gc.relocate is associated. + const Instruction *statepoint() { + const Value *token = RelocateCS.getArgument(0); + + // This takes care both of relocates for call statepoints and relocates + // on normal path of invoke statepoint. + if (!isa(token)) { + return cast(token); + } + + // This relocate is on exceptional path of an invoke statepoint + const BasicBlock *invokeBB = + cast(token)->getParent()->getUniquePredecessor(); + + assert(invokeBB && "safepoints should have unique landingpads"); + assert(invokeBB->getTerminator() && "safepoint block should be well formed"); + assert(isStatepoint(invokeBB->getTerminator())); + + return invokeBB->getTerminator(); + } + /// The index into the associate statepoint's argument list + /// which contains the base pointer of the pointer whose + /// relocation this gc.relocate describes. + unsigned basePtrIndex() { + return cast(RelocateCS.getArgument(1))->getZExtValue(); + } + /// The index into the associate statepoint's argument list which + /// contains the pointer whose relocation this gc.relocate describes. + unsigned derivedPtrIndex() { + return cast(RelocateCS.getArgument(2))->getZExtValue(); + } + Value *basePtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + basePtrIndex()); + } + Value *derivedPtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + derivedPtrIndex()); + } +}; + +template +std::vector + StatepointBase:: + getRelocates(ImmutableStatepoint &IS) { + + std::vector res; + + ImmutableCallSite StatepointCS = IS.getCallSite(); + + // Search for relocated pointers. Note that working backwards from the + // gc_relocates ensures that we only get pairs which are actually relocated + // and used after the statepoint. + for (const User *U : StatepointCS.getInstruction()->users()) { + if (isGCRelocate(U)) { + res.push_back(GCRelocateOperands(U)); + } + } + + if (!StatepointCS.isInvoke()) { + return res; + } + + // We need to scan thorough exceptional relocations if it is invoke statepoint + LandingPadInst *LandingPad = + cast(StatepointCS.getInstruction())->getLandingPadInst(); + + // Search for extract value from landingpad instruction to which + // gc relocates will be attached + for (const User *LandingPadUser : LandingPad->users()) { + if (!isa(LandingPadUser)) { + continue; + } + + // gc relocates should be attached to this extract value + for (const User *U : LandingPadUser->users()) { + if (isGCRelocate(U)) { + res.push_back(GCRelocateOperands(U)); + } + } + } + return res; +} + +} +#endif diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h new file mode 100644 index 0000000..e241121 --- /dev/null +++ b/include/llvm/IR/TrackingMDRef.h @@ -0,0 +1,170 @@ +//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// References to metadata that track RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TRACKINGMDREF_H +#define LLVM_IR_TRACKINGMDREF_H + +#include "llvm/IR/MetadataTracking.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class Metadata; +class MDNode; +class ValueAsMetadata; + +/// \brief Tracking metadata reference. +/// +/// This class behaves like \a TrackingVH, but for metadata. +class TrackingMDRef { + Metadata *MD; + +public: + TrackingMDRef() : MD(nullptr) {} + explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } + + TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } + TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } + TrackingMDRef &operator=(TrackingMDRef &&X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + retrack(X); + return *this; + } + TrackingMDRef &operator=(const TrackingMDRef &X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + track(); + return *this; + } + ~TrackingMDRef() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD) { + untrack(); + this->MD = MD; + track(); + } + + /// \brief Check whether this has a trivial destructor. + /// + /// If \c MD isn't replaceable, the destructor will be a no-op. + bool hasTrivialDestructor() const { + return !MD || !MetadataTracking::isReplaceable(*MD); + } + + bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } + bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } + +private: + void track() { + if (MD) + MetadataTracking::track(MD); + } + void untrack() { + if (MD) + MetadataTracking::untrack(MD); + } + void retrack(TrackingMDRef &X) { + assert(MD == X.MD && "Expected values to match"); + if (X.MD) { + MetadataTracking::retrack(X.MD, MD); + X.MD = nullptr; + } + } +}; + +/// \brief Typed tracking ref. +/// +/// Track refererences of a particular type. It's useful to use this for \a +/// MDNode and \a ValueAsMetadata. +template class TypedTrackingMDRef { + TrackingMDRef Ref; + +public: + TypedTrackingMDRef() {} + explicit TypedTrackingMDRef(T *MD) : Ref(static_cast(MD)) {} + + TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} + TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} + TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { + Ref = std::move(X.Ref); + return *this; + } + TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { + Ref = X.Ref; + return *this; + } + + T *get() const { return (T *)Ref.get(); } + operator T *() const { return get(); } + T *operator->() const { return get(); } + T &operator*() const { return *get(); } + + bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } + bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } + + void reset() { Ref.reset(); } + void reset(T *MD) { Ref.reset(static_cast(MD)); } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } +}; + +typedef TypedTrackingMDRef TrackingMDNodeRef; +typedef TypedTrackingMDRef TrackingValueAsMetadataRef; + +// Expose the underlying metadata to casting. +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(const TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index a36fb0f..c2073c7 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -313,6 +313,9 @@ public: typedef Type * const *subtype_iterator; subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef subtypes() const { + return makeArrayRef(subtype_begin(), subtype_end()); + } typedef std::reverse_iterator subtype_reverse_iterator; subtype_reverse_iterator subtype_rbegin() const { diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h index cea66a4..73a63ad 100644 --- a/include/llvm/IR/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -31,6 +31,7 @@ class TypeFinder { // To avoid walking constant expressions multiple times and other IR // objects, we keep several helper maps. DenseSet VisitedConstants; + DenseSet VisitedMetadata; DenseSet VisitedTypes; std::vector StructTypes; diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 033cd3e..160d71b 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -77,7 +77,7 @@ public: typedef PointerIntPair UserRef; private: - Use(const Use &U) LLVM_DELETED_FUNCTION; + Use(const Use &U) = delete; /// Destructor - Only for zap() ~Use() { diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 5df459b..7d8205d 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -45,8 +45,8 @@ struct UseListOrder { } private: - UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; - UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder(const UseListOrder &X) = delete; + UseListOrder &operator=(const UseListOrder &X) = delete; }; typedef std::vector UseListOrderStack; diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index f578227..d39378d 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -33,8 +33,8 @@ template struct OperandTraits; class User : public Value { - User(const User &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + User(const User &) = delete; + void *operator new(size_t) = delete; template friend struct HungoffOperandTraits; virtual void anchor(); diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 67665be..b7213a6 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -37,7 +37,6 @@ class GlobalVariable; class InlineAsm; class Instruction; class LLVMContext; -class MDNode; class Module; class StringRef; class Twine; @@ -70,9 +69,9 @@ class Value { Type *VTy; Use *UseList; - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. friend class ValueHandleBase; - ValueName *Name; + PointerIntPair NameAndIsUsedByMD; const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? @@ -107,17 +106,12 @@ protected: private: template // UseT == 'Use' or 'const Use' class use_iterator_impl - : public std::iterator { - typedef std::iterator super; - + : public std::iterator { UseT *U; explicit use_iterator_impl(UseT *u) : U(u) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - use_iterator_impl() : U() {} bool operator==(const use_iterator_impl &x) const { return U == x.U; } @@ -148,17 +142,12 @@ private: template // UserTy == 'User' or 'const User' class user_iterator_impl - : public std::iterator { - typedef std::iterator super; - + : public std::iterator { use_iterator_impl UI; explicit user_iterator_impl(Use *U) : UI(U) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - user_iterator_impl() {} bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } @@ -189,15 +178,10 @@ private: } Use &getUse() const { return *UI; } - - /// \brief Return the operand # of this use in its User. - /// - /// FIXME: Replace all callers with a direct call to Use::getOperandNo. - unsigned getOperandNo() const { return UI->getOperandNo(); } }; - void operator=(const Value &) LLVM_DELETED_FUNCTION; - Value(const Value &) LLVM_DELETED_FUNCTION; + void operator=(const Value &) = delete; + Value(const Value &) = delete; protected: Value(Type *Ty, unsigned scid); @@ -226,10 +210,14 @@ public: LLVMContext &getContext() const; // \brief All values can potentially be named. - bool hasName() const { return Name != nullptr; } - ValueName *getValueName() const { return Name; } - void setValueName(ValueName *VN) { Name = VN; } + bool hasName() const { return getValueName() != nullptr; } + ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } + void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } + +private: + void destroyValueName(); +public: /// \brief Return a constant reference to the value's name. /// /// This is cheap and guaranteed to return the same reference as long as the @@ -258,6 +246,13 @@ public: /// guaranteed to be empty. void replaceAllUsesWith(Value *V); + /// replaceUsesOutsideBlock - Go through the uses list for this definition and + /// make each use point to "V" instead of "this" when the use is outside the + /// block. 'This's use list is expected to have at least one element. + /// Unlike replaceAllUsesWith this function does not support basic block + /// values or constant users. + void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); + //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -276,6 +271,8 @@ public: return iterator_range(use_begin(), use_end()); } + bool user_empty() const { return UseList == nullptr; } + typedef user_iterator_impl user_iterator; typedef user_iterator_impl const_user_iterator; user_iterator user_begin() { return user_iterator(UseList); } @@ -345,9 +342,7 @@ public: ConstantStructVal, // This is an instance of ConstantStruct ConstantVectorVal, // This is an instance of ConstantVector ConstantPointerNullVal, // This is an instance of ConstantPointerNull - GenericMDNodeVal, // This is an instance of GenericMDNode - MDNodeFwdDeclVal, // This is an instance of MDNodeFwdDecl - MDStringVal, // This is an instance of MDString + MetadataAsValueVal, // This is an instance of MetadataAsValue InlineAsmVal, // This is an instance of InlineAsm InstructionVal, // This is an instance of Instruction // Enum values starting at InstructionVal are used for Instructions; @@ -397,6 +392,9 @@ public: /// \brief Return true if there is a value handle associated with this value. bool hasValueHandle() const { return HasValueHandle; } + /// \brief Return true if there is metadata referencing this value. + bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } + /// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// /// Returns the original uncasted value. If this is called on a non-pointer @@ -471,7 +469,8 @@ public: /// /// This is the greatest alignment value supported by load, store, and alloca /// instructions, and global values. - static const unsigned MaximumAlignment = 1u << 29; + static const unsigned MaxAlignmentExponent = 29; + static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; /// \brief Mutate the type of this Value to be of the specified type. /// @@ -680,13 +679,6 @@ template <> struct isa_impl { } }; -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::GenericMDNodeVal || - Val.getValueID() == Value::MDNodeFwdDeclVal; - } -}; - // Value* is only 4-byte aligned. template<> class PointerLikeTypeTraits { diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 460210e..355748e 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -56,55 +56,48 @@ private: PointerIntPair PrevPair; ValueHandleBase *Next; - // A subclass may want to store some information along with the value - // pointer. Allow them to do this by making the value pointer a pointer-int - // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this - // access. - PointerIntPair VP; + Value* V; - ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; + ValueHandleBase(const ValueHandleBase&) = delete; public: explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {} + : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(V) { + if (isValid(V)) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) { + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); } ~ValueHandleBase() { - if (isValid(VP.getPointer())) + if (isValid(V)) RemoveFromUseList(); } Value *operator=(Value *RHS) { - if (VP.getPointer() == RHS) return RHS; - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS); - if (isValid(VP.getPointer())) AddToUseList(); + if (V == RHS) return RHS; + if (isValid(V)) RemoveFromUseList(); + V = RHS; + if (isValid(V)) AddToUseList(); return RHS; } Value *operator=(const ValueHandleBase &RHS) { - if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS.VP.getPointer()); - if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); - return VP.getPointer(); + if (V == RHS.V) return RHS.V; + if (isValid(V)) RemoveFromUseList(); + V = RHS.V; + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); + return V; } - Value *operator->() const { return getValPtr(); } - Value &operator*() const { return *getValPtr(); } + Value *operator->() const { return V; } + Value &operator*() const { return *V; } protected: - Value *getValPtr() const { return VP.getPointer(); } - - void setValPtrInt(unsigned K) { VP.setInt(K); } - unsigned getValPtrInt() const { return VP.getInt(); } + Value *getValPtr() const { return V; } static bool isValid(Value *V) { return V && @@ -123,7 +116,7 @@ private: HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - /// \brief Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. /// /// List is the address of either the head of the list or a Next node within /// the existing use list. @@ -132,7 +125,7 @@ private: /// \brief Add this ValueHandle to the use list after Node. void AddToExistingUseListAfter(ValueHandleBase *Node); - /// \brief Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. void AddToUseList(); /// \brief Remove this ValueHandle from its current use list. void RemoveFromUseList(); @@ -197,23 +190,20 @@ class AssertingVH friend struct DenseMapInfo >; #ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } + Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } + void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } #else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - void setValPtr(ValueTy *P) { ThePtr = P; } + Value *ThePtr; + Value *getRawValPtr() const { return ThePtr; } + void setRawValPtr(Value *P) { ThePtr = P; } #endif - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. + // Convert a ValueTy*, which may be const, to the raw Value*. static Value *GetAsValue(Value *V) { return V; } static Value *GetAsValue(const Value *V) { return const_cast(V); } + ValueTy *getValPtr() const { return static_cast(getRawValPtr()); } + void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } + public: #ifndef NDEBUG AssertingVH() : ValueHandleBase(Assert) {} @@ -221,7 +211,7 @@ public: AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else AssertingVH() : ThePtr(nullptr) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} + AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} #endif operator ValueTy*() const { @@ -244,27 +234,23 @@ public: // Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. template struct DenseMapInfo > { - typedef DenseMapInfo PointerInfo; static inline AssertingVH getEmptyKey() { - return AssertingVH(PointerInfo::getEmptyKey()); + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getEmptyKey()); + return Res; } - static inline T* getTombstoneKey() { - return AssertingVH(PointerInfo::getTombstoneKey()); + static inline AssertingVH getTombstoneKey() { + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getTombstoneKey()); + return Res; } static unsigned getHashValue(const AssertingVH &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val.getRawValPtr()); } -#ifndef NDEBUG static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - // Avoid downcasting AssertingVH to T*, as empty/tombstone keys may not - // be properly aligned pointers to T*. - return LHS.ValueHandleBase::getValPtr() == RHS.ValueHandleBase::getValPtr(); + return DenseMapInfo::isEqual(LHS.getRawValPtr(), + RHS.getRawValPtr()); } -#else - static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - return LHS == RHS; - } -#endif }; template diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index aa8a29d..08d6d17 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -27,11 +27,13 @@ #define LLVM_IR_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/UniqueLock.h" #include "llvm/Support/type_traits.h" #include +#include namespace llvm { @@ -79,11 +81,13 @@ class ValueMap { friend class ValueMapCallbackVH; typedef ValueMapCallbackVH ValueMapCVH; typedef DenseMap > MapT; + typedef DenseMap MDMapT; typedef typename Config::ExtraData ExtraData; MapT Map; + std::unique_ptr MDMap; ExtraData Data; - ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; - ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; + ValueMap(const ValueMap&) = delete; + ValueMap& operator=(const ValueMap&) = delete; public: typedef KeyT key_type; typedef ValueT mapped_type; @@ -91,12 +95,19 @@ public: typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} + : Map(NumInitBuckets), Data() {} explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} + : Map(NumInitBuckets), Data(Data) {} ~ValueMap() {} + bool hasMD() const { return MDMap; } + MDMapT &MD() { + if (!MDMap) + MDMap.reset(new MDMapT); + return *MDMap; + } + typedef ValueMapIterator iterator; typedef ValueMapConstIterator const_iterator; inline iterator begin() { return iterator(Map.begin()); } @@ -110,7 +121,10 @@ public: /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } - void clear() { Map.clear(); } + void clear() { + Map.clear(); + MDMap.reset(); + } /// Return 1 if the specified key is in the map, 0 otherwise. size_type count(const KeyT &Val) const { @@ -210,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH { : CallbackVH(const_cast(static_cast(Key))), Map(Map) {} + // Private constructor used to create empty/tombstone DenseMap keys. + ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {} + public: KeyT Unwrap() const { return cast_or_null(getValPtr()); } @@ -252,19 +269,18 @@ public: template struct DenseMapInfo > { typedef ValueMapCallbackVH VH; - typedef DenseMapInfo PointerInfo; static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), nullptr); + return VH(DenseMapInfo::getEmptyKey()); } static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), nullptr); + return VH(DenseMapInfo::getTombstoneKey()); } static unsigned getHashValue(const VH &Val) { - return PointerInfo::getHashValue(Val.Unwrap()); + return DenseMapInfo::getHashValue(Val.Unwrap()); } static unsigned getHashValue(const KeyT &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val); } static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 0272e20..43bd123 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -77,8 +77,8 @@ class VerifierPass { public: explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} - PreservedAnalyses run(Module *M); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Module &M); + PreservedAnalyses run(Function &F); static StringRef name() { return "VerifierPass"; } }; -- cgit v1.1