diff options
Diffstat (limited to 'include/llvm/IR')
36 files changed, 1753 insertions, 1897 deletions
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 443892b..d0d1b5e 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -89,6 +89,7 @@ public: ///< often, so lazy binding isn't worthwhile NonNull, ///< Pointer is known to be not null Dereferenceable, ///< Pointer is known to be dereferenceable + DereferenceableOrNull, ///< Pointer is either null or dereferenceable NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack @@ -136,6 +137,8 @@ public: static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes); + static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, + uint64_t Bytes); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -185,6 +188,10 @@ public: /// dereferenceable attribute (or zero if unknown). uint64_t getDereferenceableBytes() const; + /// \brief Returns the number of dereferenceable_or_null bytes from the + /// dereferenceable_or_null attribute (or zero if unknown). + uint64_t getDereferenceableOrNullBytes() const; + /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -287,6 +294,12 @@ public: AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, uint64_t Bytes) const; + /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// the given index. Since attribute sets are immutable, this returns a new + /// set. + AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// @@ -331,6 +344,10 @@ public: /// \brief Get the number of dereferenceable bytes (or zero if unknown). uint64_t getDereferenceableBytes(unsigned Index) const; + /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// unknown). + uint64_t getDereferenceableOrNullBytes(unsigned Index) const; + /// \brief Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; @@ -411,6 +428,7 @@ class AttrBuilder { uint64_t Alignment; uint64_t StackAlignment; uint64_t DerefBytes; + uint64_t DerefOrNullBytes; public: AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} explicit AttrBuilder(uint64_t Val) @@ -476,6 +494,10 @@ public: /// attribute exists (zero is returned otherwise). uint64_t getDereferenceableBytes() const { return DerefBytes; } + /// \brief Retrieve the number of dereferenceable_or_null bytes, if the + /// dereferenceable_or_null attribute exists (zero is returned otherwise). + uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// \brief This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); @@ -488,6 +510,10 @@ public: /// internally in Attribute. AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + /// \brief This turns the number of dereferenceable_or_null bytes into the + /// form used internally in Attribute. + AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); + /// \brief Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 8f5cdeb..a71946e 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -28,33 +28,25 @@ class LandingPadInst; class TerminatorInst; class LLVMContext; class BlockAddress; +class Function; -template<> struct ilist_traits<Instruction> - : public SymbolTableListTraits<Instruction, BasicBlock> { +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits<BasicBlock> + : public SymbolTableListTraits<BasicBlock, Function> { - /// \brief Return a node that marks the end of a list. - /// - /// The sentinel is relative to this instance, so we use a non-static - /// method. - Instruction *createSentinel() const { - // Since i(p)lists always publicly derive from their corresponding traits, - // placing a data member in this class will augment the i(p)list. But since - // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, - // there is a legal viable downcast from it to NodeTy. We use this trick to - // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the - // sentinel. Dereferencing the sentinel is forbidden (save the - // ilist_node<NodeTy>), so no one will ever notice the superposition. - return static_cast<Instruction*>(&Sentinel); - } - static void destroySentinel(Instruction*) {} + BasicBlock *createSentinel() const; + static void destroySentinel(BasicBlock*) {} + + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} - Instruction *provideInitialHead() const { return createSentinel(); } - Instruction *ensureHead(Instruction*) const { return createSentinel(); } - static void noteHead(Instruction*, Instruction*) {} + static ValueSymbolTable *getSymTab(Function *ItemParent); private: - mutable ilist_half_node<Instruction> Sentinel; + mutable ilist_half_node<BasicBlock> Sentinel; }; + /// \brief LLVM Basic Block Representation /// /// This represents a single basic block in LLVM. A basic block is simply a @@ -113,7 +105,7 @@ public: BasicBlock *InsertBefore = nullptr) { return new BasicBlock(Context, Name, Parent, InsertBefore); } - ~BasicBlock(); + ~BasicBlock() override; /// \brief Return the enclosing method, or null if none. const Function *getParent() const { return Parent; } @@ -176,7 +168,9 @@ public: void removeFromParent(); /// \brief Unlink 'this' from the containing function and delete it. - void eraseFromParent(); + /// + // \returns an iterator pointing to the element after the erased one. + iplist<BasicBlock>::iterator eraseFromParent(); /// \brief Unlink this basic block from its current function and insert it /// into the function that \p MovePos lives in, right before \p MovePos. @@ -332,6 +326,12 @@ private: } }; +// createSentinel is used to get hold of the node that marks the end of the +// list... (same trick used here as in ilist_traits<Instruction>) +inline BasicBlock *ilist_traits<BasicBlock>::createSentinel() const { + return static_cast<BasicBlock*>(&Sentinel); +} + // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index 9c87936..ebace33 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -46,12 +46,13 @@ template <typename FunTy = const Function, class CallSiteBase { protected: PointerIntPair<InstrTy*, 1, bool> I; -public: + CallSiteBase() : I(nullptr, false) {} CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } - CallSiteBase(ValTy *II) { *this = get(II); } -protected: + explicit CallSiteBase(ValTy *II) { *this = get(II); } + +private: /// CallSiteBase::get - This static method is sort of like a constructor. It /// will create an appropriate call site for a Call or Invoke instruction, but /// it can also create a null initialized CallSiteBase object for something @@ -349,15 +350,13 @@ private: class CallSite : public CallSiteBase<Function, Value, User, Instruction, CallInst, InvokeInst, User::op_iterator> { - typedef CallSiteBase<Function, Value, User, Instruction, - CallInst, InvokeInst, User::op_iterator> Base; public: CallSite() {} - CallSite(Base B) : Base(B) {} - CallSite(Value* V) : Base(V) {} - CallSite(CallInst *CI) : Base(CI) {} - CallSite(InvokeInst *II) : Base(II) {} - CallSite(Instruction *II) : Base(II) {} + CallSite(CallSiteBase B) : CallSiteBase(B) {} + CallSite(CallInst *CI) : CallSiteBase(CI) {} + CallSite(InvokeInst *II) : CallSiteBase(II) {} + explicit CallSite(Instruction *II) : CallSiteBase(II) {} + explicit CallSite(Value *V) : CallSiteBase(V) {} bool operator==(const CallSite &CS) const { return I == CS.I; } bool operator!=(const CallSite &CS) const { return I != CS.I; } @@ -371,13 +370,13 @@ private: /// ImmutableCallSite - establish a view to a call site for examination class ImmutableCallSite : public CallSiteBase<> { - typedef CallSiteBase<> Base; public: - ImmutableCallSite(const Value* V) : Base(V) {} - ImmutableCallSite(const CallInst *CI) : Base(CI) {} - ImmutableCallSite(const InvokeInst *II) : Base(II) {} - ImmutableCallSite(const Instruction *II) : Base(II) {} - ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {} + ImmutableCallSite() {} + ImmutableCallSite(const CallInst *CI) : CallSiteBase(CI) {} + ImmutableCallSite(const InvokeInst *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Instruction *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Value *V) : CallSiteBase(V) {} + ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {} }; } // End llvm namespace diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index e271a14..fb6ca3b 100644 --- a/include/llvm/IR/ConstantFolder.h +++ b/include/llvm/IR/ConstantFolder.h @@ -118,34 +118,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 59be653..70437e6 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -547,7 +547,7 @@ class ConstantDataSequential : public Constant { protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} - ~ConstantDataSequential() { delete Next; } + ~ConstantDataSequential() override { delete Next; } static Constant *getImpl(StringRef Bytes, Type *Ty); @@ -1057,41 +1057,43 @@ public: /// all elements must be Constant's. /// /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Constant *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { return getGetElementPtr( - C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), + Ty, C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, Constant *Idx, + static Constant *getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); + return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, Constant *Idx) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, Idx, true); + return getGetElementPtr(Ty, C, Idx, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } static Constant *getExtractElement(Constant *Vec, Constant *Idx, diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 97a7b83..db87654 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -30,38 +30,17 @@ namespace llvm { class Value; class Constant; class LLVMContext; - class MDNode; class StringRef; - class DIBasicType; - class DICompileUnit; - class DICompositeType; - class DIDerivedType; - class DIDescriptor; - class DIFile; - class DIEnumerator; - class DIType; - class DIGlobalVariable; - class DIImportedEntity; - class DINameSpace; - class DIVariable; - class DISubrange; - class DILexicalBlockFile; - class DILexicalBlock; - class DIScope; - class DISubprogram; - class DITemplateTypeParameter; - class DITemplateValueParameter; - class DIObjCProperty; class DIBuilder { Module &M; LLVMContext &VMContext; - MDNode *TempEnumTypes; - MDNode *TempRetainTypes; - MDNode *TempSubprograms; - MDNode *TempGVs; - MDNode *TempImportedModules; + TempMDTuple TempEnumTypes; + TempMDTuple TempRetainTypes; + TempMDTuple TempSubprograms; + TempMDTuple TempGVs; + TempMDTuple TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value @@ -125,26 +104,25 @@ namespace llvm { /// source location information in the back end /// without actually changing the output (e.g., /// when using optimization remarks). - DICompileUnit createCompileUnit(unsigned Lang, StringRef File, - StringRef Dir, StringRef Producer, - bool isOptimized, StringRef Flags, - unsigned RV, - StringRef SplitName = StringRef(), - DebugEmissionKind Kind = FullDebug, - bool EmitDebugInfo = true); + MDCompileUnit *createCompileUnit(unsigned Lang, StringRef File, + StringRef Dir, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RV, StringRef SplitName = "", + DebugEmissionKind Kind = FullDebug, + bool EmitDebugInfo = true); /// createFile - Create a file descriptor to hold debugging information /// for a file. - DIFile createFile(StringRef Filename, StringRef Directory); + MDFile *createFile(StringRef Filename, StringRef Directory); /// createEnumerator - Create a single enumerator value. - DIEnumerator createEnumerator(StringRef Name, int64_t Val); + MDEnumerator *createEnumerator(StringRef Name, int64_t Val); /// \brief Create a DWARF unspecified type. - DIBasicType createUnspecifiedType(StringRef Name); + MDBasicType *createUnspecifiedType(StringRef Name); /// \brief Create C++11 nullptr type. - DIBasicType createNullPtrType(); + MDBasicType *createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -152,36 +130,36 @@ namespace llvm { /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIBasicType createBasicType(StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding); + MDBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding); /// createQualifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type /// @param FromTy Base Type. - DIDerivedType createQualifiedType(unsigned Tag, DIType FromTy); + MDDerivedType *createQualifiedType(unsigned Tag, MDType *FromTy); /// createPointerType - Create debugging information entry for a pointer. /// @param PointeeTy Type pointed by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Name Pointer type name. (optional) - DIDerivedType - createPointerType(DIType PointeeTy, uint64_t SizeInBits, - uint64_t AlignInBits = 0, StringRef Name = StringRef()); + MDDerivedType *createPointerType(MDType *PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = ""); /// \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, - uint64_t SizeInBits, - uint64_t AlignInBits = 0); + MDDerivedType *createMemberPointerType(MDType *PointeeTy, MDType *Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. - DIDerivedType createReferenceType(unsigned Tag, DIType RTy); + MDDerivedType *createReferenceType(unsigned Tag, MDType *RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. @@ -189,11 +167,11 @@ namespace llvm { /// @param File File where this type is defined. /// @param LineNo Line number. /// @param Context The surrounding context for the typedef. - DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File, - unsigned LineNo, DIDescriptor Context); + MDDerivedType *createTypedef(MDType *Ty, StringRef Name, MDFile *File, + unsigned LineNo, MDScope *Context); /// createFriend - Create debugging information entry for a 'friend'. - DIDerivedType createFriend(DIType Ty, DIType FriendTy); + MDDerivedType *createFriend(MDType *Ty, MDType *FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. @@ -202,8 +180,8 @@ namespace llvm { /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private - DIDerivedType createInheritance(DIType Ty, DIType BaseTy, - uint64_t BaseOffset, unsigned Flags); + MDDerivedType *createInheritance(MDType *Ty, MDType *BaseTy, + uint64_t BaseOffset, unsigned Flags); /// createMemberType - Create debugging information entry for a member. /// @param Scope Member scope. @@ -215,10 +193,11 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIDerivedType - createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, DIType Ty); + MDDerivedType *createMemberType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + MDType *Ty); /// createStaticMemberType - Create debugging information entry for a /// C++ static data member. @@ -229,10 +208,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, - DIType Ty, unsigned Flags, - llvm::Constant *Val); + MDDerivedType *createStaticMemberType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNo, + MDType *Ty, unsigned Flags, + llvm::Constant *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -245,11 +224,10 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. - DIDerivedType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - MDNode *PropertyNode); + MDDerivedType *createObjCIVar(StringRef Name, MDFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + MDType *Ty, MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. @@ -260,12 +238,11 @@ namespace llvm { /// @param SetterName Name of the Objective C property setter selector. /// @param PropertyAttributes Objective C property attributes. /// @param Ty Type. - DIObjCProperty createObjCProperty(StringRef Name, - DIFile File, unsigned LineNumber, - StringRef GetterName, - StringRef SetterName, - unsigned PropertyAttributes, - DIType Ty); + MDObjCProperty *createObjCProperty(StringRef Name, MDFile *File, + unsigned LineNumber, + StringRef GetterName, + StringRef SetterName, + unsigned PropertyAttributes, MDType *Ty); /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. @@ -283,14 +260,14 @@ namespace llvm { /// for more info. /// @param TemplateParms Template type parameters. /// @param UniqueIdentifier A unique identifier for the class. - DICompositeType createClassType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom, DIArray Elements, - DIType VTableHolder = DIType(), - MDNode *TemplateParms = nullptr, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createClassType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + MDType *DerivedFrom, DIArray Elements, + MDType *VTableHolder = nullptr, + MDNode *TemplateParms = nullptr, + StringRef UniqueIdentifier = ""); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -303,13 +280,11 @@ namespace llvm { /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the struct. - DICompositeType createStructType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, unsigned RunTimeLang = 0, - DIType VTableHolder = DIType(), - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createStructType( + MDScope *Scope, StringRef Name, MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + MDType *DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, + MDType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -322,19 +297,20 @@ namespace llvm { /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the union. - DICompositeType createUnionType( - DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createUnionType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, DIArray Elements, + unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = ""); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. - DITemplateTypeParameter - createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty); + MDTemplateTypeParameter * + createTemplateTypeParameter(MDScope *Scope, StringRef Name, MDType *Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -342,46 +318,46 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val Constant parameter value. - DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, - StringRef Name, - DIType Ty, - Constant *Val); + MDTemplateValueParameter *createTemplateValueParameter(MDScope *Scope, + StringRef Name, + MDType *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. - DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, - StringRef Name, - DIType Ty, - StringRef Val); + MDTemplateValueParameter *createTemplateTemplateParameter(MDScope *Scope, + StringRef Name, + MDType *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. - DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, - StringRef Name, - DIType Ty, - DIArray Val); + MDTemplateValueParameter *createTemplateParameterPack(MDScope *Scope, + StringRef Name, + MDType *Ty, + DIArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + MDCompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, + MDType *Ty, DIArray Subscripts); /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + MDCompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, + MDType *Ty, DIArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. @@ -394,10 +370,10 @@ namespace llvm { /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// @param UniqueIdentifier A unique identifier for the enum. - DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createEnumerationType( + MDScope *Scope, StringRef Name, MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, + MDType *UnderlyingType, StringRef UniqueIdentifier = ""); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -405,39 +381,39 @@ namespace llvm { /// includes return type at 0th index. /// @param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - DISubroutineType createSubroutineType(DIFile File, - DITypeArray ParameterTypes, - unsigned Flags = 0); + MDSubroutineType *createSubroutineType(MDFile *File, + DITypeArray ParameterTypes, + unsigned Flags = 0); - /// createArtificialType - Create a new DIType with "artificial" flag set. - DIType createArtificialType(DIType Ty); + /// createArtificialType - Create a new MDType* with "artificial" flag set. + MDType *createArtificialType(MDType *Ty); - /// createObjectPointerType - Create a new DIType with the "object pointer" + /// createObjectPointerType - Create a new MDType* with the "object pointer" /// flag set. - DIType createObjectPointerType(DIType Ty); + MDType *createObjectPointerType(MDType *Ty); /// \brief Create a permanent forward-declared type. - DICompositeType createForwardDecl(unsigned Tag, StringRef Name, - DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createForwardDecl(unsigned Tag, StringRef Name, + MDScope *Scope, MDFile *F, unsigned Line, + unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = ""); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableCompositeType( - unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, unsigned Flags = DIDescriptor::FlagFwdDecl, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createReplaceableCompositeType( + unsigned Tag, StringRef Name, MDScope *Scope, MDFile *F, unsigned Line, + unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, unsigned Flags = DebugNode::FlagFwdDecl, + StringRef UniqueIdentifier = ""); - /// retainType - Retain DIType in a module even if it is not referenced + /// retainType - Retain MDType* in a module even if it is not referenced /// through debug info anchors. - void retainType(DIType T); + void retainType(MDType *T); /// createUnspecifiedParameter - Create unspecified parameter type /// for a subroutine type. - DIBasicType createUnspecifiedParameter(); + MDBasicType *createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. DIArray getOrCreateArray(ArrayRef<Metadata *> Elements); @@ -447,8 +423,7 @@ namespace llvm { /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. - DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); - + MDSubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); /// createGlobalVariable - Create a new descriptor for the specified /// variable. @@ -462,19 +437,19 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. - DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, - unsigned LineNo, DITypeRef Ty, - bool isLocalToUnit, - llvm::Constant *Val, - MDNode *Decl = nullptr); + MDGlobalVariable *createGlobalVariable(MDScope *Context, StringRef Name, + StringRef LinkageName, MDFile *File, + unsigned LineNo, MDType *Ty, + bool isLocalToUnit, + llvm::Constant *Val, + MDNode *Decl = nullptr); /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. - DIGlobalVariable createTempGlobalVariableFwdDecl( - DIDescriptor Context, StringRef Name, StringRef LinkageName, - DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, - llvm::Constant *Val, MDNode *Decl = nullptr); + MDGlobalVariable *createTempGlobalVariableFwdDecl( + MDScope *Context, StringRef Name, StringRef LinkageName, MDFile *File, + unsigned LineNo, MDType *Ty, bool isLocalToUnit, llvm::Constant *Val, + MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified /// local variable. @@ -490,29 +465,29 @@ namespace llvm { /// @param Flags Flags, e.g. artificial variable. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. - DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, - DIFile File, unsigned LineNo, - DITypeRef Ty, bool AlwaysPreserve = false, - unsigned Flags = 0, - unsigned ArgNo = 0); + MDLocalVariable *createLocalVariable(unsigned Tag, MDScope *Scope, + StringRef Name, MDFile *File, + unsigned LineNo, MDType *Ty, + bool AlwaysPreserve = false, + unsigned Flags = 0, + unsigned ArgNo = 0); /// 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<uint64_t> Addr = None); - DIExpression createExpression(ArrayRef<int64_t> Addr); + MDExpression *createExpression(ArrayRef<uint64_t> Addr = None); + MDExpression *createExpression(ArrayRef<int64_t> Addr); /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// /// @param OffsetInBits Offset of the piece in bits. /// @param SizeInBits Size of the piece in bits. - DIExpression createBitPieceExpression(unsigned OffsetInBits, - unsigned SizeInBits); + MDExpression *createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in MDSubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -527,49 +502,35 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createFunction(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + MDSubprogram * + createFunction(MDScope *Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createTempFunctionFwdDecl - Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. - DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); - + MDSubprogram *createTempFunctionFwdDecl( + MDScope *Scope, StringRef Name, StringRef LinkageName, MDFile *File, + unsigned LineNo, MDSubroutineType *Ty, bool isLocalToUnit, + bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, + bool isOptimized = false, Function *Fn = nullptr, + MDNode *TParam = nullptr, MDNode *Decl = nullptr); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. - DISubprogram createFunction(DIScopeRef Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + MDSubprogram * + createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createMethod - Create a new descriptor for the specified C++ method. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in MDSubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -587,17 +548,13 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createMethod(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned Virtuality = 0, unsigned VTableIndex = 0, - DIType VTableHolder = DIType(), - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr); + MDSubprogram * + createMethod(MDScope *Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, + unsigned VTableIndex = 0, MDType *VTableHolder = nullptr, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. @@ -605,9 +562,8 @@ namespace llvm { /// @param Name Name of this namespace /// @param File Source file /// @param LineNo Line number - DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo); - + MDNamespace *createNameSpace(MDScope *Scope, StringRef Name, MDFile *File, + unsigned LineNo); /// createLexicalBlockFile - This creates a descriptor for a lexical /// block with a new file attached. This merely extends the existing @@ -615,8 +571,8 @@ namespace llvm { /// @param Scope Lexical block. /// @param File Source file. /// @param Discriminator DWARF path discriminator value. - DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File, - unsigned Discriminator = 0); + MDLexicalBlockFile *createLexicalBlockFile(MDScope *Scope, MDFile *File, + unsigned Discriminator = 0); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -624,60 +580,63 @@ namespace llvm { /// @param File Source file. /// @param Line Line number. /// @param Col Column number. - DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col); + MDLexicalBlock *createLexicalBlock(MDScope *Scope, MDFile *File, + unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line); + MDImportedEntity *createImportedModule(MDScope *Context, MDNamespace *NS, + unsigned Line); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS An aliased namespace /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, - unsigned Line); + MDImportedEntity *createImportedModule(MDScope *Context, + MDImportedEntity *NS, unsigned Line); /// \brief Create a descriptor for an imported function. /// @param Context The scope this module is imported into /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number - DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, - unsigned Line, - StringRef Name = StringRef()); - DIImportedEntity createImportedDeclaration(DIScope Context, - DIImportedEntity NS, - unsigned Line, - StringRef Name = StringRef()); + MDImportedEntity *createImportedDeclaration(MDScope *Context, + DebugNode *Decl, unsigned Line, + StringRef Name = ""); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, BasicBlock *InsertAtEnd); + Instruction *insertDeclare(llvm::Value *Storage, MDLocalVariable *VarInfo, + MDExpression *Expr, const MDLocation *DL, + BasicBlock *InsertAtEnd); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, Instruction *InsertBefore); + Instruction *insertDeclare(llvm::Value *Storage, MDLocalVariable *VarInfo, + MDExpression *Expr, const MDLocation *DL, + Instruction *InsertBefore); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + MDLocalVariable *VarInfo, + MDExpression *Expr, + const MDLocation *DL, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. @@ -685,24 +644,45 @@ namespace llvm { /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + MDLocalVariable *VarInfo, + MDExpression *Expr, + const MDLocation *DL, 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); + void replaceVTableHolder(MDCompositeType *&T, + MDCompositeType *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, + void replaceArrays(MDCompositeType *&T, DIArray Elements, DIArray TParems = DIArray()); + + /// \brief Replace a temporary node. + /// + /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c + /// Replacement. + /// + /// If \c Replacement is the same as \c N.get(), instead call \a + /// MDNode::replaceWithUniqued(). In this case, the uniqued node could + /// have a different address, so we return the final address. + template <class NodeTy> + NodeTy *replaceTemporary(TempMDNode &&N, NodeTy *Replacement) { + if (N.get() == Replacement) + return cast<NodeTy>(MDNode::replaceWithUniqued(std::move(N))); + + N->replaceAllUsesWith(Replacement); + return Replacement; + } }; } // end namespace llvm diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 0163c05..18b0c72 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -58,1292 +58,365 @@ class DIObjCProperty; /// \brief Maps from type identifier to the actual MDNode. typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; -class DIHeaderFieldIterator - : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t, - const StringRef *, StringRef> { - StringRef Header; - StringRef Current; +class DIDescriptor { + MDNode *N; public: - DIHeaderFieldIterator() {} - explicit DIHeaderFieldIterator(StringRef Header) - : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} - StringRef operator*() const { return Current; } - const StringRef *operator->() const { return &Current; } - DIHeaderFieldIterator &operator++() { - increment(); - return *this; - } - DIHeaderFieldIterator operator++(int) { - DIHeaderFieldIterator X(*this); - increment(); - return X; - } - bool operator==(const DIHeaderFieldIterator &X) const { - return Current.data() == X.Current.data(); - } - bool operator!=(const DIHeaderFieldIterator &X) const { - return !(*this == X); - } + DIDescriptor(const MDNode *N = nullptr) : N(const_cast<MDNode *>(N)) {} - StringRef getHeader() const { return Header; } - StringRef getCurrent() const { return Current; } - StringRef getPrefix() const { - if (Current.begin() == Header.begin()) - return StringRef(); - return Header.slice(0, Current.begin() - Header.begin() - 1); - } - StringRef getSuffix() const { - if (Current.end() == Header.end()) - return StringRef(); - 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 <class T> 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"); - StringRef Suffix = getSuffix(); - Current = Suffix.slice(0, Suffix.find('\0')); - } + operator MDNode *() const { return N; } + MDNode *operator->() const { return N; } + MDNode &operator*() const { return *N; } }; -/// \brief A thin wraper around MDNode to access encoded debug info. -/// -/// This should not be stored in a container, because the underlying MDNode may -/// change in certain situations. -class DIDescriptor { - // Befriends DIRef so DIRef can befriend the protected member - // function: getFieldAs<DIRef>. - template <typename T> friend class DIRef; +#define DECLARE_SIMPLIFY_DESCRIPTOR(DESC) \ + class DESC; \ + template <> struct simplify_type<const DESC>; \ + template <> struct simplify_type<DESC>; +DECLARE_SIMPLIFY_DESCRIPTOR(DIDescriptor) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubrange) +DECLARE_SIMPLIFY_DESCRIPTOR(DIEnumerator) +DECLARE_SIMPLIFY_DESCRIPTOR(DIScope) +DECLARE_SIMPLIFY_DESCRIPTOR(DIType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIBasicType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIDerivedType) +DECLARE_SIMPLIFY_DESCRIPTOR(DICompositeType) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubroutineType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIFile) +DECLARE_SIMPLIFY_DESCRIPTOR(DICompileUnit) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubprogram) +DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlock) +DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) +DECLARE_SIMPLIFY_DESCRIPTOR(DINameSpace) +DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) +DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) +DECLARE_SIMPLIFY_DESCRIPTOR(DIGlobalVariable) +DECLARE_SIMPLIFY_DESCRIPTOR(DIVariable) +DECLARE_SIMPLIFY_DESCRIPTOR(DIExpression) +DECLARE_SIMPLIFY_DESCRIPTOR(DILocation) +DECLARE_SIMPLIFY_DESCRIPTOR(DIObjCProperty) +DECLARE_SIMPLIFY_DESCRIPTOR(DIImportedEntity) +#undef DECLARE_SIMPLIFY_DESCRIPTOR + +typedef DebugNodeArray DIArray; +typedef MDTypeRefArray DITypeArray; +typedef DebugNodeRef DIDescriptorRef; +typedef MDScopeRef DIScopeRef; +typedef MDTypeRef DITypeRef; + +class DISubrange { + MDSubrange *N; public: - /// \brief Accessibility flags. - /// - /// The three accessibility flags are mutually exclusive and rolled together - /// in the first two bits. - enum { -#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<unsigned> &SplitFlags); - -protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; - DIDescriptor getDescriptorField(unsigned Elt) const; + DISubrange(const MDSubrange *N = nullptr) : N(const_cast<MDSubrange *>(N)) {} - template <typename DescTy> DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt)); - } + operator MDSubrange *() const { return N; } + MDSubrange *operator->() const { return N; } + MDSubrange &operator*() const { return *N; } +}; - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; +class DIEnumerator { + MDEnumerator *N; public: - explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} - - bool Verify() const; - - MDNode *get() const { return const_cast<MDNode *>(DbgNode); } - operator MDNode *() const { return get(); } - MDNode *operator->() const { return get(); } - MDNode &operator*() const { - assert(get() && "Expected valid pointer"); - 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. - 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); } - - size_t getNumHeaderFields() const { - return std::distance(DIHeaderFieldIterator(getHeader()), - DIHeaderFieldIterator()); - } - - 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 (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) - if (!Index) - return I; - return header_end(); - } - - StringRef getHeaderField(unsigned Index) const { - return *getHeaderIterator(Index); - } - - template <class T> T getHeaderFieldAs(unsigned Index) const { - return getHeaderIterator(Index).getNumber<T>(); - } - - uint16_t getTag() const { - if (auto *N = dyn_cast_or_null<DebugNode>(get())) - return N->getTag(); - return 0; - } + DIEnumerator(const MDEnumerator *N = nullptr) + : N(const_cast<MDEnumerator *>(N)) {} - bool isDerivedType() const { return get() && isa<MDDerivedTypeBase>(get()); } - bool isCompositeType() const { - return get() && isa<MDCompositeTypeBase>(get()); - } - bool isSubroutineType() const { - return get() && isa<MDSubroutineType>(get()); - } - bool isBasicType() const { return get() && isa<MDBasicType>(get()); } - bool isVariable() const { return get() && isa<MDLocalVariable>(get()); } - bool isSubprogram() const { return get() && isa<MDSubprogram>(get()); } - bool isGlobalVariable() const { - return get() && isa<MDGlobalVariable>(get()); - } - bool isScope() const { return get() && isa<MDScope>(get()); } - bool isFile() const { return get() && isa<MDFile>(get()); } - bool isCompileUnit() const { return get() && isa<MDCompileUnit>(get()); } - bool isNameSpace() const{ return get() && isa<MDNamespace>(get()); } - bool isLexicalBlockFile() const { - return get() && isa<MDLexicalBlockFile>(get()); - } - bool isLexicalBlock() const { - return get() && isa<MDLexicalBlockBase>(get()); - } - bool isSubrange() const { return get() && isa<MDSubrange>(get()); } - bool isEnumerator() const { return get() && isa<MDEnumerator>(get()); } - bool isType() const { return get() && isa<MDType>(get()); } - bool isTemplateTypeParameter() const { - return get() && isa<MDTemplateTypeParameter>(get()); - } - bool isTemplateValueParameter() const { - return get() && isa<MDTemplateValueParameter>(get()); - } - bool isObjCProperty() const { return get() && isa<MDObjCProperty>(get()); } - bool isImportedEntity() const { - return get() && isa<MDImportedEntity>(get()); - } - bool isExpression() const { return get() && isa<MDExpression>(get()); } - - void print(raw_ostream &OS) const; - void dump() const; - - /// \brief Replace all uses of debug info referenced by this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); + operator MDEnumerator *() const { return N; } + MDEnumerator *operator->() const { return N; } + MDEnumerator &operator*() const { return *N; } }; -#define RETURN_FROM_RAW(VALID, UNUSED) \ - do { \ - auto *N = get(); \ - assert(N && "Expected non-null in accessor"); \ - return VALID; \ - } while (false) -#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ - do { \ - auto *N = get(); \ - assert(N && "Expected non-null in accessor"); \ - return DESC(dyn_cast_or_null<MDNode>(VALID)); \ - } while (false) -#define RETURN_REF_FROM_RAW(REF, VALID) \ - do { \ - auto *N = get(); \ - assert(N && "Expected non-null in accessor"); \ - return REF::get(VALID); \ - } while (false) - -/// \brief This is used to represent ranges, for array bounds. -class DISubrange : public DIDescriptor { -public: - explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - DISubrange(const MDSubrange *N) : DIDescriptor(N) {} - - MDSubrange *get() const { - return cast_or_null<MDSubrange>(DIDescriptor::get()); - } - operator MDSubrange *() const { return get(); } - MDSubrange *operator->() const { return get(); } - MDSubrange &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - int64_t getLo() const { RETURN_FROM_RAW(N->getLo(), 0); } - int64_t getCount() const { RETURN_FROM_RAW(N->getCount(), 0); } - bool Verify() const; -}; +class DIScope { + MDScope *N; -/// \brief This descriptor holds an array of nodes with type T. -template <typename T> class DITypedArray : public DIDescriptor { public: - explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} - unsigned getNumElements() const { - return DbgNode ? DbgNode->getNumOperands() : 0; - } - T getElement(unsigned Idx) const { return getFieldAs<T>(Idx); } + DIScope(const MDScope *N = nullptr) : N(const_cast<MDScope *>(N)) {} + + operator DIDescriptor() const { return N; } + operator MDScope *() const { return N; } + MDScope *operator->() const { return N; } + MDScope &operator*() const { return *N; } }; -typedef DITypedArray<DIDescriptor> DIArray; +class DIType { + MDType *N; -/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). -/// -/// FIXME: it seems strange that this doesn't have either a reference to the -/// type/precision or a file/line pair for location info. -class DIEnumerator : public DIDescriptor { public: - explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIEnumerator(const MDEnumerator *N) : DIDescriptor(N) {} - - MDEnumerator *get() const { - return cast_or_null<MDEnumerator>(DIDescriptor::get()); - } - operator MDEnumerator *() const { return get(); } - MDEnumerator *operator->() const { return get(); } - MDEnumerator &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } + DIType(const MDType *N = nullptr) : N(const_cast<MDType *>(N)) {} - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - int64_t getEnumValue() const { RETURN_FROM_RAW(N->getValue(), 0); } - bool Verify() const; + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDType *() const { return N; } + MDType *operator->() const { return N; } + MDType &operator*() const { return *N; } }; -template <typename T> class DIRef; -typedef DIRef<DIDescriptor> DIDescriptorRef; -typedef DIRef<DIScope> DIScopeRef; -typedef DIRef<DIType> DITypeRef; -typedef DITypedArray<DITypeRef> DITypeArray; +class DIBasicType { + MDBasicType *N; -/// \brief A base class for various scopes. -/// -/// Although, implementation-wise, DIScope is the parent class of most -/// other DIxxx classes, including DIType and its descendants, most of -/// DIScope's descendants are not a substitutable subtype of -/// DIScope. The DIDescriptor::isScope() method only is true for -/// DIScopes that are scopes in the strict lexical scope sense -/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. -class DIScope : public DIDescriptor { public: - explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope(const MDScope *N) : DIDescriptor(N) {} - - MDScope *get() const { return cast_or_null<MDScope>(DIDescriptor::get()); } - operator MDScope *() const { return get(); } - MDScope *operator->() const { return get(); } - MDScope &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - /// \brief Get the parent scope. - /// - /// Gets the parent scope for this scope node or returns a default - /// constructed scope. - DIScopeRef getContext() const; - /// \brief Get the scope name. - /// - /// If the scope node has a name, return that, else return an empty string. - StringRef getName() const; - StringRef getFilename() const; - StringRef getDirectory() const; - - /// \brief Generate a reference to this DIScope. - /// - /// Uses the type identifier instead of the actual MDNode if possible, to - /// help type uniquing. - DIScopeRef getRef() const; + DIBasicType(const MDBasicType *N = nullptr) + : N(const_cast<MDBasicType *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator MDBasicType *() const { return N; } + MDBasicType *operator->() const { return N; } + MDBasicType &operator*() const { return *N; } }; -/// \brief Represents reference to a DIDescriptor. -/// -/// Abstracts over direct and identifier-based metadata references. -template <typename T> class DIRef { - template <typename DescTy> - friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; - friend DIScopeRef DIScope::getContext() const; - friend DIScopeRef DIScope::getRef() const; - friend class DIType; - - /// \brief Val can be either a MDNode or a MDString. - /// - /// In the latter, MDString specifies the type identifier. - const Metadata *Val; - explicit DIRef(const Metadata *V); +class DIDerivedType { + MDDerivedTypeBase *N; public: - T resolve(const DITypeIdentifierMap &Map) const; - StringRef getName() const; - operator Metadata *() const { return const_cast<Metadata *>(Val); } - - static DIRef get(const Metadata *MD) { return DIRef(MD); } + DIDerivedType(const MDDerivedTypeBase *N = nullptr) + : N(const_cast<MDDerivedTypeBase *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator MDDerivedTypeBase *() const { return N; } + MDDerivedTypeBase *operator->() const { return N; } + MDDerivedTypeBase &operator*() const { return *N; } }; -template <typename T> -T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const { - if (!Val) - return T(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD); - - const MDString *MS = cast<MDString>(Val); - // Find the corresponding MDNode. - DITypeIdentifierMap::const_iterator Iter = Map.find(MS); - assert(Iter != Map.end() && "Identifier not in the type map?"); - assert(DIDescriptor(Iter->second).isType() && - "MDNode in DITypeIdentifierMap should be a DIType."); - return T(Iter->second); -} - -template <typename T> StringRef DIRef<T>::getName() const { - if (!Val) - return StringRef(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD).getName(); - - const MDString *MS = cast<MDString>(Val); - return MS->getString(); -} - -/// \brief Handle fields that are references to DIDescriptors. -template <> -DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DIDescriptorRef. -template <> DIRef<DIDescriptor>::DIRef(const Metadata *V); - -/// \brief Handle fields that are references to DIScopes. -template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DIScopeRef. -template <> DIRef<DIScope>::DIRef(const Metadata *V); - -/// \brief Handle fields that are references to DITypes. -template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DITypeRef. -template <> DIRef<DIType>::DIRef(const Metadata *V); - -/// \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. -class DIType : public DIScope { -public: - explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - DIType(const MDType *N) : DIScope(N) {} - - MDType *get() const { return cast_or_null<MDType>(DIDescriptor::get()); } - operator MDType *() const { return get(); } - MDType *operator->() const { return get(); } - MDType &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - operator DITypeRef() const { - assert(isType() && - "constructing DITypeRef from an MDNode that is not a type"); - return DITypeRef(&*getRef()); - } - - bool Verify() const; +class DICompositeType { + MDCompositeTypeBase *N; - DIScopeRef getContext() const { - RETURN_REF_FROM_RAW(DIScopeRef, N->getScope()); - } - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - uint64_t getSizeInBits() const { RETURN_FROM_RAW(N->getSizeInBits(), 0); } - uint64_t getAlignInBits() const { RETURN_FROM_RAW(N->getAlignInBits(), 0); } - // FIXME: Offset is only used for DW_TAG_member nodes. Making every type - // carry this is just plain insane. - uint64_t getOffsetInBits() const { RETURN_FROM_RAW(N->getOffsetInBits(), 0); } - unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - bool isAppleBlockExtension() const { - return (getFlags() & FlagAppleBlock) != 0; - } - bool isBlockByrefStruct() const { - return (getFlags() & FlagBlockByrefStruct) != 0; - } - bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; } - bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { return (getFlags() & FlagVector) != 0; } - bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } - bool isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } - bool isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } - bool isValid() const { return DbgNode && isType(); } -}; - -/// \brief A basic type, like 'int' or 'float'. -class DIBasicType : public DIType { public: - explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - DIBasicType(const MDBasicType *N) : DIType(N) {} - - MDBasicType *get() const { - return cast_or_null<MDBasicType>(DIDescriptor::get()); - } - operator MDBasicType *() const { return get(); } - MDBasicType *operator->() const { return get(); } - MDBasicType &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - unsigned getEncoding() const { RETURN_FROM_RAW(N->getEncoding(), 0); } - - bool Verify() const; + DICompositeType(const MDCompositeTypeBase *N = nullptr) + : N(const_cast<MDCompositeTypeBase *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator MDCompositeTypeBase *() const { return N; } + MDCompositeTypeBase *operator->() const { return N; } + MDCompositeTypeBase &operator*() const { return *N; } }; -/// \brief A simple derived type -/// -/// Like a const qualified type, a typedef, a pointer or reference, et cetera. -/// Or, a data member of a class/struct/union. -class DIDerivedType : public DIType { -public: - explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - DIDerivedType(const MDDerivedTypeBase *N) : DIType(N) {} - - MDDerivedTypeBase *get() const { - return cast_or_null<MDDerivedTypeBase>(DIDescriptor::get()); - } - operator MDDerivedTypeBase *() const { return get(); } - MDDerivedTypeBase *operator->() const { return get(); } - MDDerivedTypeBase &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DITypeRef getTypeDerivedFrom() const { - RETURN_REF_FROM_RAW(DITypeRef, N->getBaseType()); - } - - /// \brief Return property node, if this ivar is associated with one. - MDNode *getObjCProperty() const { - if (auto *N = dyn_cast<MDDerivedType>(get())) - return dyn_cast_or_null<MDNode>(N->getExtraData()); - return nullptr; - } +class DISubroutineType { + MDSubroutineType *N; - DITypeRef getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - if (auto *N = dyn_cast<MDDerivedType>(get())) - return DITypeRef::get(N->getExtraData()); - return DITypeRef::get(nullptr); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - if (auto *N = dyn_cast<MDDerivedType>(get())) - if (auto *C = dyn_cast_or_null<ConstantAsMetadata>(N->getExtraData())) - return C->getValue(); - - return nullptr; - } - - bool Verify() const; +public: + DISubroutineType(const MDSubroutineType *N = nullptr) + : N(const_cast<MDSubroutineType *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator DICompositeType() const { return N; } + operator MDSubroutineType *() const { return N; } + MDSubroutineType *operator->() const { return N; } + MDSubroutineType &operator*() const { return *N; } }; -/// \brief Types that refer to multiple other types. -/// -/// This descriptor holds a type that can refer to multiple other types, like a -/// function or struct. -/// -/// DICompositeType is derived from DIDerivedType because some -/// composite types (such as enums) can be derived from basic types -// FIXME: Make this derive from DIType directly & just store the -// base type in a single DIType field. -class DICompositeType : public DIDerivedType { - friend class DIBuilder; - - /// \brief Set the array of member DITypes. - void setArraysHelper(MDNode *Elements, MDNode *TParams); +class DIFile { + MDFile *N; public: - explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} - DICompositeType(const MDCompositeTypeBase *N) : DIDerivedType(N) {} + DIFile(const MDFile *N = nullptr) : N(const_cast<MDFile *>(N)) {} - MDCompositeTypeBase *get() const { - return cast_or_null<MDCompositeTypeBase>(DIDescriptor::get()); - } - operator MDCompositeTypeBase *() const { return get(); } - MDCompositeTypeBase *operator->() const { return get(); } - MDCompositeTypeBase &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DIArray getElements() const { - assert(!isSubroutineType() && "no elements for DISubroutineType"); - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getElements()); - } + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDFile *() const { return N; } + MDFile *operator->() const { return N; } + MDFile &operator*() const { return *N; } +}; -private: - template <typename T> - void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { - assert( - (!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); - setArraysHelper(Elements, TParams); - } +class DICompileUnit { + MDCompileUnit *N; public: - unsigned getRunTimeLang() const { RETURN_FROM_RAW(N->getRuntimeLang(), 0); } - DITypeRef getContainingType() const { - RETURN_REF_FROM_RAW(DITypeRef, N->getVTableHolder()); - } + DICompileUnit(const MDCompileUnit *N = nullptr) + : N(const_cast<MDCompileUnit *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDCompileUnit *() const { return N; } + MDCompileUnit *operator->() const { return N; } + MDCompileUnit &operator*() const { return *N; } +}; -private: - /// \brief Set the containing type. - void setContainingType(DICompositeType ContainingType); +class DISubprogram { + MDSubprogram *N; public: - DIArray getTemplateParams() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getTemplateParams()); - } - MDString *getIdentifier() const { - RETURN_FROM_RAW(N->getRawIdentifier(), nullptr); - } - - bool Verify() const; + DISubprogram(const MDSubprogram *N = nullptr) + : N(const_cast<MDSubprogram *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDSubprogram *() const { return N; } + MDSubprogram *operator->() const { return N; } + MDSubprogram &operator*() const { return *N; } }; -class DISubroutineType : public DICompositeType { -public: - explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} - DISubroutineType(const MDSubroutineType *N) : DICompositeType(N) {} +class DILexicalBlock { + MDLexicalBlockBase *N; - MDSubroutineType *get() const { - return cast_or_null<MDSubroutineType>(DIDescriptor::get()); - } - operator MDSubroutineType *() const { return get(); } - MDSubroutineType *operator->() const { return get(); } - MDSubroutineType &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DITypedArray<DITypeRef> getTypeArray() const { - RETURN_DESCRIPTOR_FROM_RAW(DITypedArray<DITypeRef>, N->getTypeArray()); - } -}; - -/// \brief This is a wrapper for a file. -class DIFile : public DIScope { public: - explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} - DIFile(const MDFile *N) : DIScope(N) {} - - MDFile *get() const { return cast_or_null<MDFile>(DIDescriptor::get()); } - operator MDFile *() const { return get(); } - MDFile *operator->() const { return get(); } - MDFile &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } + DILexicalBlock(const MDLexicalBlockBase *N = nullptr) + : N(const_cast<MDLexicalBlockBase *>(N)) {} - /// \brief Retrieve the MDNode for the directory/file pair. - MDNode *getFileNode() const { return get(); } - bool Verify() const; + operator DIDescriptor() const { return N; } + operator MDLexicalBlockBase *() const { return N; } + MDLexicalBlockBase *operator->() const { return N; } + MDLexicalBlockBase &operator*() const { return *N; } }; -/// \brief A wrapper for a compile unit. -class DICompileUnit : public DIScope { -public: - explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} - DICompileUnit(const MDCompileUnit *N) : DIScope(N) {} - - MDCompileUnit *get() const { - return cast_or_null<MDCompileUnit>(DIDescriptor::get()); - } - operator MDCompileUnit *() const { return get(); } - MDCompileUnit *operator->() const { return get(); } - MDCompileUnit &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - dwarf::SourceLanguage getLanguage() const { - RETURN_FROM_RAW(static_cast<dwarf::SourceLanguage>(N->getSourceLanguage()), - static_cast<dwarf::SourceLanguage>(0)); - } - StringRef getProducer() const { RETURN_FROM_RAW(N->getProducer(), ""); } - bool isOptimized() const { RETURN_FROM_RAW(N->isOptimized(), false); } - StringRef getFlags() const { RETURN_FROM_RAW(N->getFlags(), ""); } - unsigned getRunTimeVersion() const { - RETURN_FROM_RAW(N->getRuntimeVersion(), 0); - } +class DILexicalBlockFile { + MDLexicalBlockFile *N; - DIArray getEnumTypes() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getEnumTypes()); - } - DIArray getRetainedTypes() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getRetainedTypes()); - } - DIArray getSubprograms() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getSubprograms()); - } - DIArray getGlobalVariables() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getGlobalVariables()); - } - DIArray getImportedEntities() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getImportedEntities()); - } - - void replaceSubprograms(DIArray Subprograms); - void replaceGlobalVariables(DIArray GlobalVariables); - - StringRef getSplitDebugFilename() const { - RETURN_FROM_RAW(N->getSplitDebugFilename(), ""); - } - unsigned getEmissionKind() const { RETURN_FROM_RAW(N->getEmissionKind(), 0); } - - bool Verify() const; -}; - -/// \brief This is a wrapper for a subprogram (e.g. a function). -class DISubprogram : public DIScope { public: - explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - DISubprogram(const MDSubprogram *N) : DIScope(N) {} - - MDSubprogram *get() const { - return cast_or_null<MDSubprogram>(DIDescriptor::get()); - } - operator MDSubprogram *() const { return get(); } - MDSubprogram *operator->() const { return get(); } - MDSubprogram &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - StringRef getDisplayName() const { RETURN_FROM_RAW(N->getDisplayName(), ""); } - StringRef getLinkageName() const { RETURN_FROM_RAW(N->getLinkageName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - - /// \brief Check if this is local (like 'static' in C). - unsigned isLocalToUnit() const { RETURN_FROM_RAW(N->isLocalToUnit(), 0); } - unsigned isDefinition() const { RETURN_FROM_RAW(N->isDefinition(), 0); } - - unsigned getVirtuality() const { RETURN_FROM_RAW(N->getVirtuality(), 0); } - unsigned getVirtualIndex() const { RETURN_FROM_RAW(N->getVirtualIndex(), 0); } - - unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } - - unsigned isOptimized() const { RETURN_FROM_RAW(N->isOptimized(), 0); } - - /// \brief Get the beginning of the scope of the function (not the name). - unsigned getScopeLineNumber() const { RETURN_FROM_RAW(N->getScopeLine(), 0); } - - DIScopeRef getContext() const { - RETURN_REF_FROM_RAW(DIScopeRef, N->getScope()); - } - DISubroutineType getType() const { - RETURN_DESCRIPTOR_FROM_RAW(DISubroutineType, N->getType()); - } - - DITypeRef getContainingType() const { - RETURN_REF_FROM_RAW(DITypeRef, N->getContainingType()); - } - - bool Verify() const; - - /// \brief Check if this provides debugging information for the function F. - bool describes(const Function *F); - - Function *getFunction() const; - - void replaceFunction(Function *F) { - if (auto *N = get()) - N->replaceFunction(F); - } - DIArray getTemplateParams() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getTemplateParams()); - } - DISubprogram getFunctionDeclaration() const { - RETURN_DESCRIPTOR_FROM_RAW(DISubprogram, N->getDeclaration()); - } - MDNode *getVariablesNodes() const { return getVariables(); } - DIArray getVariables() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getVariables()); - } - - unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - /// \brief Check for the "private" access specifier. - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - /// \brief Check for the "protected" access specifier. - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - /// \brief Check for the "public" access specifier. - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - /// \brief Check for "explicit". - bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } - /// \brief Check if this is prototyped. - bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } - - /// \brief Check if this is reference-qualified. - /// - /// Return true if this subprogram is a C++11 reference-qualified non-static - /// member function (void foo() &). - unsigned isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } + DILexicalBlockFile(const MDLexicalBlockFile *N = nullptr) + : N(const_cast<MDLexicalBlockFile *>(N)) {} - /// \brief Check if this is rvalue-reference-qualified. - /// - /// Return true if this subprogram is a C++11 rvalue-reference-qualified - /// non-static member function (void foo() &&). - unsigned isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } + operator DIDescriptor() const { return N; } + operator MDLexicalBlockFile *() const { return N; } + MDLexicalBlockFile *operator->() const { return N; } + MDLexicalBlockFile &operator*() const { return *N; } }; -/// \brief This is a wrapper for a lexical block. -class DILexicalBlock : public DIScope { -public: - explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} - DILexicalBlock(const MDLexicalBlock *N) : DIScope(N) {} +class DINameSpace { + MDNamespace *N; - MDLexicalBlockBase *get() const { - return cast_or_null<MDLexicalBlockBase>(DIDescriptor::get()); - } - operator MDLexicalBlockBase *() const { return get(); } - MDLexicalBlockBase *operator->() const { return get(); } - MDLexicalBlockBase &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - unsigned getLineNumber() const { - if (auto *N = dyn_cast<MDLexicalBlock>(get())) - return N->getLine(); - return 0; - } - unsigned getColumnNumber() const { - if (auto *N = dyn_cast<MDLexicalBlock>(get())) - return N->getColumn(); - return 0; - } - bool Verify() const; -}; - -/// \brief This is a wrapper for a lexical block with a filename change. -class DILexicalBlockFile : public DIScope { public: - explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} - DILexicalBlockFile(const MDLexicalBlockFile *N) : DIScope(N) {} - - MDLexicalBlockFile *get() const { - return cast_or_null<MDLexicalBlockFile>(DIDescriptor::get()); - } - operator MDLexicalBlockFile *() const { return get(); } - MDLexicalBlockFile *operator->() const { return get(); } - MDLexicalBlockFile &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - 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(); - } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { - RETURN_DESCRIPTOR_FROM_RAW(DILexicalBlock, N->getScope()); - } - unsigned getDiscriminator() const { - RETURN_FROM_RAW(N->getDiscriminator(), 0); - } - bool Verify() const; + DINameSpace(const MDNamespace *N = nullptr) + : N(const_cast<MDNamespace *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDNamespace *() const { return N; } + MDNamespace *operator->() const { return N; } + MDNamespace &operator*() const { return *N; } }; -/// \brief A wrapper for a C++ style name space. -class DINameSpace : public DIScope { -public: - explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} - DINameSpace(const MDNamespace *N) : DIScope(N) {} - - MDNamespace *get() const { - return cast_or_null<MDNamespace>(DIDescriptor::get()); - } - operator MDNamespace *() const { return get(); } - MDNamespace *operator->() const { return get(); } - MDNamespace &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - bool Verify() const; -}; +class DITemplateTypeParameter { + MDTemplateTypeParameter *N; -/// \brief This is a wrapper for template type parameter. -class DITemplateTypeParameter : public DIDescriptor { public: - explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - DITemplateTypeParameter(const MDTemplateTypeParameter *N) : DIDescriptor(N) {} + DITemplateTypeParameter(const MDTemplateTypeParameter *N = nullptr) + : N(const_cast<MDTemplateTypeParameter *>(N)) {} - MDTemplateTypeParameter *get() const { - return cast_or_null<MDTemplateTypeParameter>(DIDescriptor::get()); - } - operator MDTemplateTypeParameter *() const { return get(); } - MDTemplateTypeParameter *operator->() const { return get(); } - MDTemplateTypeParameter &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - bool Verify() const; + operator MDTemplateTypeParameter *() const { return N; } + MDTemplateTypeParameter *operator->() const { return N; } + MDTemplateTypeParameter &operator*() const { return *N; } }; -/// \brief This is a wrapper for template value parameter. -class DITemplateValueParameter : public DIDescriptor { -public: - explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - DITemplateValueParameter(const MDTemplateValueParameter *N) - : DIDescriptor(N) {} +class DITemplateValueParameter { + MDTemplateValueParameter *N; - MDTemplateValueParameter *get() const { - return cast_or_null<MDTemplateValueParameter>(DIDescriptor::get()); - } - operator MDTemplateValueParameter *() const { return get(); } - MDTemplateValueParameter *operator->() const { return get(); } - MDTemplateValueParameter &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } +public: + DITemplateValueParameter(const MDTemplateValueParameter *N = nullptr) + : N(const_cast<MDTemplateValueParameter *>(N)) {} - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - Metadata *getValue() const { RETURN_FROM_RAW(N->getValue(), nullptr); } - bool Verify() const; + operator MDTemplateValueParameter *() const { return N; } + MDTemplateValueParameter *operator->() const { return N; } + MDTemplateValueParameter &operator*() const { return *N; } }; -/// \brief This is a wrapper for a global variable. -class DIGlobalVariable : public DIDescriptor { - DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } +class DIGlobalVariable { + MDGlobalVariable *N; public: - explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIGlobalVariable(const MDGlobalVariable *N) : DIDescriptor(N) {} + DIGlobalVariable(const MDGlobalVariable *N = nullptr) + : N(const_cast<MDGlobalVariable *>(N)) {} - MDGlobalVariable *get() const { - return cast_or_null<MDGlobalVariable>(DIDescriptor::get()); - } - operator MDGlobalVariable *() const { return get(); } - MDGlobalVariable *operator->() const { return get(); } - MDGlobalVariable &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - StringRef getDisplayName() const { RETURN_FROM_RAW(N->getDisplayName(), ""); } - StringRef getLinkageName() const { RETURN_FROM_RAW(N->getLinkageName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - unsigned isLocalToUnit() const { RETURN_FROM_RAW(N->isLocalToUnit(), 0); } - unsigned isDefinition() const { RETURN_FROM_RAW(N->isDefinition(), 0); } - - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - StringRef getFilename() const { return getFile().getFilename(); } - StringRef getDirectory() const { return getFile().getDirectory(); } - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - - GlobalVariable *getGlobal() const; - Constant *getConstant() const { - if (auto *N = get()) - if (auto *C = dyn_cast_or_null<ConstantAsMetadata>(N->getVariable())) - return C->getValue(); - return nullptr; - } - DIDerivedType getStaticDataMemberDeclaration() const { - RETURN_DESCRIPTOR_FROM_RAW(DIDerivedType, - N->getStaticDataMemberDeclaration()); - } - - bool Verify() const; + operator DIDescriptor() const { return N; } + operator MDGlobalVariable *() const { return N; } + MDGlobalVariable *operator->() const { return N; } + MDGlobalVariable &operator*() const { return *N; } }; -/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). -class DIVariable : public DIDescriptor { - unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } +class DIVariable { + MDLocalVariable *N; public: - explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIVariable(const MDLocalVariable *N) : DIDescriptor(N) {} + DIVariable(const MDLocalVariable *N = nullptr) + : N(const_cast<MDLocalVariable *>(N)) {} - MDLocalVariable *get() const { - return cast_or_null<MDLocalVariable>(DIDescriptor::get()); - } - operator MDLocalVariable *() const { return get(); } - MDLocalVariable *operator->() const { return get(); } - MDLocalVariable &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - unsigned getArgNumber() const { RETURN_FROM_RAW(N->getArg(), 0); } - - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - - /// \brief Return true if this variable is marked as "artificial". - bool isArtificial() const { - return (getFlags() & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getFlags() & FlagObjectPointer) != 0; - } - - /// \brief If this variable is inlined then return inline location. - MDNode *getInlinedAt() const { - RETURN_DESCRIPTOR_FROM_RAW(DIDescriptor, N->getInlinedAt()); - } - - bool Verify() const; - - /// \brief Check if this is a "__block" variable (Apple Blocks). - bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { - return (getType().resolve(Map)).isBlockByrefStruct(); - } - - /// \brief Check if this is an inlined function argument. - bool isInlinedFnArgument(const Function *CurFn); - - /// \brief Return the size reported by the variable's type. - unsigned getSizeInBits(const DITypeIdentifierMap &Map); - - void printExtendedName(raw_ostream &OS) const; + operator MDLocalVariable *() const { return N; } + MDLocalVariable *operator->() const { return N; } + MDLocalVariable &operator*() const { return *N; } }; -/// \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 { -public: - explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIExpression(const MDExpression *N) : DIDescriptor(N) {} - - MDExpression *get() const { - return cast_or_null<MDExpression>(DIDescriptor::get()); - } - operator MDExpression *() const { return get(); } - MDExpression *operator->() const { return get(); } - MDExpression &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - // Don't call this. Call isValid() directly. - bool Verify() const = delete; - - /// \brief Return the number of elements in the complex expression. - unsigned getNumElements() const { return get()->getNumElements(); } - - /// \brief return the Idx'th complex address element. - uint64_t getElement(unsigned I) const { return get()->getElement(I); } - - /// \brief Return whether this is a piece of an aggregate variable. - 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; - MDExpression::element_iterator I; - Operand() {} - Operand(MDExpression::element_iterator 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 { - MDExpression::element_iterator In = I; - std::advance(In, N); - return *In; - } - operator uint64_t () const { return *I; } - /// \brief Returns underlying MDExpression::element_iterator. - const MDExpression::element_iterator &getBase() const { return I; } - /// \brief Returns the next operand. - iterator getNext() const; - }; - - /// \brief An iterator for DIExpression elements. - class iterator : public std::iterator<std::input_iterator_tag, StringRef, - unsigned, const Operand*, Operand> { - friend class Operand; - MDExpression::element_iterator I; - Operand Tmp; - - public: - iterator(MDExpression::element_iterator I) : I(I) {} - 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 { return get()->elements_begin(); } - iterator end() const { return get()->elements_end(); } -}; +class DIExpression { + MDExpression *N; -/// \brief This object holds location information. -/// -/// This object is not associated with any DWARF tag. -class DILocation : public DIDescriptor { public: - explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - - MDLocation *get() const { - return cast_or_null<MDLocation>(DIDescriptor::get()); - } - operator MDLocation *() const { return get(); } - MDLocation *operator->() const { return get(); } - MDLocation &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - 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; - bool atSameLineAs(const DILocation &Other) const { - return (getLineNumber() == Other.getLineNumber() && - getFilename() == Other.getFilename()); - } - /// \brief Get the DWAF discriminator. - /// - /// DWARF discriminators are used to distinguish identical file locations for - /// instructions that are on different basic blocks. If two instructions are - /// inside the same lexical block and are in different basic blocks, we - /// create a new lexical block with identical location as the original but - /// with a different discriminator value - /// (lib/Transforms/Util/AddDiscriminators.cpp for details). - unsigned getDiscriminator() const { - // Since discriminators are associated with lexical blocks, make - // sure this location is a lexical block before retrieving its - // value. - return getScope().isLexicalBlockFile() - ? DILexicalBlockFile( - cast<MDNode>(cast<MDLocation>(DbgNode)->getScope())) - .getDiscriminator() - : 0; - } + DIExpression(const MDExpression *N = nullptr) + : N(const_cast<MDExpression *>(N)) {} - /// \brief Generate a new discriminator value for this location. - unsigned computeNewDiscriminator(LLVMContext &Ctx); - - /// \brief Return a copy of this location with a different scope. - DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); + operator MDExpression *() const { return N; } + MDExpression *operator->() const { return N; } + MDExpression &operator*() const { return *N; } }; -class DIObjCProperty : public DIDescriptor { +class DILocation { + MDLocation *N; + public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - DIObjCProperty(const MDObjCProperty *N) : DIDescriptor(N) {} + DILocation(const MDLocation *N = nullptr) : N(const_cast<MDLocation *>(N)) {} - MDObjCProperty *get() const { - return cast_or_null<MDObjCProperty>(DIDescriptor::get()); - } - operator MDObjCProperty *() const { return get(); } - MDObjCProperty *operator->() const { return get(); } - MDObjCProperty &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } + operator MDLocation *() const { return N; } + MDLocation *operator->() const { return N; } + MDLocation &operator*() const { return *N; } +}; - StringRef getObjCPropertyName() const { RETURN_FROM_RAW(N->getName(), ""); } - DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } +class DIObjCProperty { + MDObjCProperty *N; - StringRef getObjCPropertyGetterName() const { - RETURN_FROM_RAW(N->getGetterName(), ""); - } - StringRef getObjCPropertySetterName() const { - RETURN_FROM_RAW(N->getSetterName(), ""); - } - unsigned getAttributes() const { RETURN_FROM_RAW(N->getAttributes(), 0); } - bool isReadOnlyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - /// \brief Get the type. - /// - /// \note Objective-C doesn't have an ODR, so there is no benefit in storing - /// the type as a DITypeRef here. - DIType getType() const { RETURN_DESCRIPTOR_FROM_RAW(DIType, N->getType()); } +public: + DIObjCProperty(const MDObjCProperty *N = nullptr) + : N(const_cast<MDObjCProperty *>(N)) {} - bool Verify() const; + operator MDObjCProperty *() const { return N; } + MDObjCProperty *operator->() const { return N; } + MDObjCProperty &operator*() const { return *N; } }; -/// \brief An imported module (C++ using directive or similar). -class DIImportedEntity : public DIDescriptor { -public: - DIImportedEntity() = default; - explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} - DIImportedEntity(const MDImportedEntity *N) : DIDescriptor(N) {} +class DIImportedEntity { + MDImportedEntity *N; - MDImportedEntity *get() const { - return cast_or_null<MDImportedEntity>(DIDescriptor::get()); - } - operator MDImportedEntity *() const { return get(); } - MDImportedEntity *operator->() const { return get(); } - MDImportedEntity &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } +public: + DIImportedEntity(const MDImportedEntity *N = nullptr) + : N(const_cast<MDImportedEntity *>(N)) {} - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - DIDescriptorRef getEntity() const { - RETURN_REF_FROM_RAW(DIDescriptorRef, N->getEntity()); - } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - bool Verify() const; + operator DIDescriptor() const { return N; } + operator MDImportedEntity *() const { return N; } + MDImportedEntity *operator->() const { return N; } + MDImportedEntity &operator*() const { return *N; } }; -#undef RETURN_FROM_RAW -#undef RETURN_DESCRIPTOR_FROM_RAW -#undef RETURN_REF_FROM_RAW +#define SIMPLIFY_DESCRIPTOR(DESC) \ + template <> struct simplify_type<const DESC> { \ + typedef Metadata *SimpleType; \ + static SimpleType getSimplifiedValue(const DESC &DI) { return DI; } \ + }; \ + template <> struct simplify_type<DESC> : simplify_type<const DESC> {}; +SIMPLIFY_DESCRIPTOR(DIDescriptor) +SIMPLIFY_DESCRIPTOR(DISubrange) +SIMPLIFY_DESCRIPTOR(DIEnumerator) +SIMPLIFY_DESCRIPTOR(DIScope) +SIMPLIFY_DESCRIPTOR(DIType) +SIMPLIFY_DESCRIPTOR(DIBasicType) +SIMPLIFY_DESCRIPTOR(DIDerivedType) +SIMPLIFY_DESCRIPTOR(DICompositeType) +SIMPLIFY_DESCRIPTOR(DISubroutineType) +SIMPLIFY_DESCRIPTOR(DIFile) +SIMPLIFY_DESCRIPTOR(DICompileUnit) +SIMPLIFY_DESCRIPTOR(DISubprogram) +SIMPLIFY_DESCRIPTOR(DILexicalBlock) +SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) +SIMPLIFY_DESCRIPTOR(DINameSpace) +SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) +SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) +SIMPLIFY_DESCRIPTOR(DIGlobalVariable) +SIMPLIFY_DESCRIPTOR(DIVariable) +SIMPLIFY_DESCRIPTOR(DIExpression) +SIMPLIFY_DESCRIPTOR(DILocation) +SIMPLIFY_DESCRIPTOR(DIObjCProperty) +SIMPLIFY_DESCRIPTOR(DIImportedEntity) +#undef SIMPLIFY_DESCRIPTOR /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1356,16 +429,6 @@ DISubprogram getDISubprogram(const Function *F); /// \brief Find underlying composite type. DICompositeType getDICompositeType(DIType T); -/// \brief Create a new inlined variable based on current variable. -/// -/// @param DV Current Variable. -/// @param InlinedScope Location at current variable is inlined. -DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); - -/// \brief Remove inlined scope from the variable. -DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); - /// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); @@ -1375,6 +438,7 @@ DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); +bool stripDebugInfo(Function &F); /// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d7563fc..62373c4 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -41,6 +41,101 @@ namespace llvm { +/// \brief Pointer union between a subclass of DebugNode and MDString. +/// +/// \a MDCompositeType can be referenced via an \a MDString unique identifier. +/// This class allows some type safety in the face of that, requiring either a +/// node of a particular type or an \a MDString. +template <class T> class TypedDebugNodeRef { + const Metadata *MD = nullptr; + +public: + TypedDebugNodeRef() = default; + TypedDebugNodeRef(std::nullptr_t) {} + + /// \brief Construct from a raw pointer. + explicit TypedDebugNodeRef(const Metadata *MD) : MD(MD) { + assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref"); + } + + template <class U> + TypedDebugNodeRef( + const TypedDebugNodeRef<U> &X, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : MD(X) {} + + operator Metadata *() const { return const_cast<Metadata *>(MD); } + + bool operator==(const TypedDebugNodeRef<T> &X) const { return MD == X.MD; }; + bool operator!=(const TypedDebugNodeRef<T> &X) const { return MD != X.MD; }; + + /// \brief Create a reference. + /// + /// Get a reference to \c N, using an \a MDString reference if available. + static TypedDebugNodeRef get(const T *N); + + template <class MapTy> T *resolve(const MapTy &Map) const { + if (!MD) + return nullptr; + + if (auto *Typed = dyn_cast<T>(MD)) + return const_cast<T *>(Typed); + + auto *S = cast<MDString>(MD); + auto I = Map.find(S); + assert(I != Map.end() && "Missing identifier in type map"); + return cast<T>(I->second); + } +}; + +typedef TypedDebugNodeRef<DebugNode> DebugNodeRef; +typedef TypedDebugNodeRef<MDScope> MDScopeRef; +typedef TypedDebugNodeRef<MDType> MDTypeRef; + +class MDTypeRefArray { + const MDTuple *N = nullptr; + +public: + MDTypeRefArray(const MDTuple *N) : N(N) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + MDTypeRef operator[](unsigned I) const { return MDTypeRef(N->getOperand(I)); } + + class iterator : std::iterator<std::input_iterator_tag, MDTypeRef, + std::ptrdiff_t, void, MDTypeRef> { + MDNode::op_iterator I = nullptr; + + public: + iterator() = default; + explicit iterator(MDNode::op_iterator I) : I(I) {} + MDTypeRef operator*() const { return MDTypeRef(*I); } + iterator &operator++() { + ++I; + return *this; + } + iterator operator++(int) { + iterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } + }; + + // FIXME: Fix callers and remove condition on N. + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + /// \brief Tagged DWARF-like metadata node. /// /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, @@ -57,7 +152,7 @@ protected: assert(Tag < 1u << 16); SubclassData16 = Tag; } - ~DebugNode() {} + ~DebugNode() = default; template <class Ty> Ty *getOperandAs(unsigned I) const { return cast_or_null<Ty>(getOperand(I)); @@ -78,6 +173,28 @@ protected: public: unsigned getTag() const { return SubclassData16; } + /// \brief Debug info flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. + enum DIFlags { +#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<unsigned> &SplitFlags); + + DebugNodeRef getRef() const { return DebugNodeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -106,6 +223,18 @@ public: } }; +template <class T> +struct simplify_type<const TypedDebugNodeRef<T>> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TypedDebugNodeRef<T> &MD) { + return MD; + } +}; + +template <class T> +struct simplify_type<TypedDebugNodeRef<T>> + : simplify_type<const TypedDebugNodeRef<T>> {}; + /// \brief Generic tagged DWARF-like metadata node. /// /// An un-specialized DWARF-like metadata node. The first operand is a @@ -192,27 +321,30 @@ class MDSubrange : public DebugNode { friend class MDNode; int64_t Count; - int64_t Lo; + int64_t LowerBound; - MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, + int64_t LowerBound) : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), - Count(Count), Lo(Lo) {} - ~MDSubrange() {} + Count(Count), LowerBound(LowerBound) {} + ~MDSubrange() = default; - static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, - StorageType Storage, bool ShouldCreate = true); + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, + int64_t LowerBound, StorageType Storage, + bool ShouldCreate = true); TempMDSubrange cloneImpl() const { - return getTemporary(getContext(), getCount(), getLo()); + return getTemporary(getContext(), getCount(), getLowerBound()); } public: - DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t LowerBound = 0), + (Count, LowerBound)) TempMDSubrange clone() const { return cloneImpl(); } - int64_t getLo() const { return Lo; } + int64_t getLowerBound() const { return LowerBound; } int64_t getCount() const { return Count; } static bool classof(const Metadata *MD) { @@ -234,7 +366,7 @@ class MDEnumerator : public DebugNode { ArrayRef<Metadata *> Ops) : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), Value(Value) {} - ~MDEnumerator() {} + ~MDEnumerator() = default; static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, StringRef Name, StorageType Storage, @@ -279,20 +411,30 @@ protected: MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef<Metadata *> Ops) : DebugNode(C, ID, Storage, Tag, Ops) {} - ~MDScope() {} + ~MDScope() = default; public: - /// \brief Return the underlying file. + MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); } + + inline StringRef getFilename() const; + inline StringRef getDirectory() const; + + StringRef getName() const; + MDScopeRef getScope() const; + + /// \brief Return the raw underlying file. /// /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file /// (it\em is the file). If \c this is an \a MDFile, we need to return \c /// this. Otherwise, return the first operand, which is where all other /// subclasses store their file pointer. - Metadata *getFile() const { + Metadata *getRawFile() const { return isa<MDFile>(this) ? const_cast<MDScope *>(this) : static_cast<Metadata *>(getOperand(0)); } + MDScopeRef getRef() const { return MDScopeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -322,7 +464,7 @@ class MDFile : public MDScope { MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} - ~MDFile() {} + ~MDFile() = default; static MDFile *getImpl(LLVMContext &Context, StringRef Filename, StringRef Directory, StorageType Storage, @@ -358,6 +500,18 @@ public: } }; +StringRef MDScope::getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; +} + +StringRef MDScope::getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; +} + /// \brief Base class for types. /// /// TODO: Remove the hardcoded name and context, since many types don't use @@ -377,7 +531,7 @@ protected: : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), SizeInBits(SizeInBits), AlignInBits(AlignInBits), OffsetInBits(OffsetInBits) {} - ~MDType() {} + ~MDType() = default; public: TempMDType clone() const { @@ -390,9 +544,11 @@ public: uint64_t getOffsetInBits() const { return OffsetInBits; } unsigned getFlags() const { return Flags; } - Metadata *getScope() const { return getOperand(1); } + MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } void setFlags(unsigned NewFlags) { @@ -400,6 +556,31 @@ public: Flags = NewFlags; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } + bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } + bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; } + bool isVirtual() const { return getFlags() & FlagVirtual; } + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + bool isObjcClassComplete() const { + return getFlags() & FlagObjcClassComplete; + } + bool isVector() const { return getFlags() & FlagVector; } + bool isStaticMember() const { return getFlags() & FlagStaticMember; } + bool isLValueReference() const { return getFlags() & FlagLValueReference; } + bool isRValueReference() const { return getFlags() & FlagRValueReference; } + + MDTypeRef getRef() const { return MDTypeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -413,7 +594,7 @@ public: } }; -/// \brief Basic type. +/// \brief Basic type, like 'int' or 'float'. /// /// TODO: Split out DW_TAG_unspecified_type. /// TODO: Drop unused accessors. @@ -429,7 +610,7 @@ class MDBasicType : public MDType { : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, 0, Ops), Encoding(Encoding) {} - ~MDBasicType() {} + ~MDBasicType() = default; static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, @@ -480,10 +661,11 @@ protected: ArrayRef<Metadata *> Ops) : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedTypeBase() {} + ~MDDerivedTypeBase() = default; public: - Metadata *getBaseType() const { return getOperand(3); } + MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); } + Metadata *getRawBaseType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind || @@ -507,11 +689,11 @@ class MDDerivedType : public MDDerivedTypeBase { uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops) : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedType() {} + ~MDDerivedType() = default; static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, + StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, Metadata *ExtraData, StorageType Storage, @@ -545,11 +727,10 @@ public: (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), + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef 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)) @@ -562,7 +743,25 @@ public: /// /// 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); } + Metadata *getExtraData() const { return getRawExtraData(); } + Metadata *getRawExtraData() const { return getOperand(4); } + + /// \brief Get casted version of extra data. + /// @{ + MDTypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return MDTypeRef(getExtraData()); + } + MDObjCProperty *getObjCProperty() const { + return dyn_cast_or_null<MDObjCProperty>(getExtraData()); + } + Constant *getConstant() const { + assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; + } + /// @} static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind; @@ -584,15 +783,28 @@ protected: : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops), RuntimeLang(RuntimeLang) {} - ~MDCompositeTypeBase() {} + ~MDCompositeTypeBase() = default; public: - Metadata *getElements() const { return getOperand(4); } - Metadata *getVTableHolder() const { return getOperand(5); } - Metadata *getTemplateParams() const { return getOperand(6); } + /// \brief Get the elements of the composite type. + /// + /// \note Calling this is only valid for \a MDCompositeType. This assertion + /// can be removed once \a MDSubroutineType has been separated from + /// "composite types". + DebugNodeArray getElements() const { + assert(!isa<MDSubroutineType>(this) && "no elements for DISubroutineType"); + return cast_or_null<MDTuple>(getRawElements()); + } + MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); } + MDTemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } StringRef getIdentifier() const { return getStringOperand(7); } unsigned getRuntimeLang() const { return RuntimeLang; } + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } /// \brief Replace operands. @@ -601,20 +813,19 @@ public: /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track /// of its movement if necessary. /// @{ - void replaceElements(MDTuple *Elements) { + void replaceElements(DebugNodeArray Elements) { #ifndef NDEBUG - if (auto *Old = cast_or_null<MDTuple>(getElements())) - for (const auto &Op : Old->operands()) - assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && - "Lost a member during member list replacement"); + for (DebugNode *Op : getElements()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); #endif - replaceOperandWith(4, Elements); + replaceOperandWith(4, Elements.get()); } - void replaceVTableHolder(Metadata *VTableHolder) { + void replaceVTableHolder(MDTypeRef VTableHolder) { replaceOperandWith(5, VTableHolder); } - void replaceTemplateParams(MDTuple *TemplateParams) { - replaceOperandWith(6, TemplateParams); + void replaceTemplateParams(MDTemplateParameterArray TemplateParams) { + replaceOperandWith(6, TemplateParams.get()); } /// @} @@ -639,20 +850,20 @@ class MDCompositeType : public MDCompositeTypeBase { : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDCompositeType() {} + ~MDCompositeType() = default; static MDCompositeType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, + unsigned Line, MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, - uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, - Metadata *VTableHolder, Metadata *TemplateParams, + uint64_t Flags, DebugNodeArray Elements, unsigned RuntimeLang, + MDTypeRef VTableHolder, MDTemplateParameterArray 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); + return getImpl( + Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + RuntimeLang, VTableHolder, TemplateParams.get(), + getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); } static MDCompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -672,12 +883,12 @@ class MDCompositeType : public MDCompositeTypeBase { 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, + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DebugNodeArray Elements, + unsigned RuntimeLang, MDTypeRef VTableHolder, + MDTemplateParameterArray TemplateParams = nullptr, StringRef Identifier = ""), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, @@ -701,6 +912,14 @@ public: } }; +template <class T> TypedDebugNodeRef<T> TypedDebugNodeRef<T>::get(const T *N) { + if (N) + if (auto *Composite = dyn_cast<MDCompositeType>(N)) + if (auto *S = Composite->getRawIdentifier()) + return TypedDebugNodeRef<T>(S); + return TypedDebugNodeRef<T>(N); +} + /// \brief Type array for a subprogram. /// /// TODO: Detach from CompositeType, and fold the array of types in directly @@ -714,9 +933,15 @@ class MDSubroutineType : public MDCompositeTypeBase { : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, Ops) {} - ~MDSubroutineType() {} + ~MDSubroutineType() = default; static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + MDTypeRefArray TypeArray, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate); + } + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, Metadata *TypeArray, StorageType Storage, bool ShouldCreate = true); @@ -725,12 +950,18 @@ class MDSubroutineType : public MDCompositeTypeBase { } public: + DEFINE_MDNODE_GET(MDSubroutineType, + (unsigned Flags, MDTypeRefArray TypeArray), + (Flags, TypeArray)) DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), (Flags, TypeArray)) TempMDSubroutineType clone() const { return cloneImpl(); } - Metadata *getTypeArray() const { return getElements(); } + MDTypeRefArray getTypeArray() const { + return cast_or_null<MDTuple>(getRawTypeArray()); + } + Metadata *getRawTypeArray() const { return getRawElements(); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubroutineTypeKind; @@ -753,22 +984,23 @@ class MDCompileUnit : public MDScope { : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} - ~MDCompileUnit() {} + ~MDCompileUnit() = default; static MDCompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *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, + unsigned EmissionKind, MDCompositeTypeArray EnumTypes, + MDTypeArray RetainedTypes, MDSubprogramArray Subprograms, + MDGlobalVariableArray GlobalVariables, + MDImportedEntityArray 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); + return getImpl( + Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), + IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, + EnumTypes.get(), RetainedTypes.get(), Subprograms.get(), + GlobalVariables.get(), ImportedEntities.get(), Storage, ShouldCreate); } static MDCompileUnit * getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, @@ -789,12 +1021,13 @@ class MDCompileUnit : public MDScope { 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), + (unsigned SourceLanguage, MDFile *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + MDCompositeTypeArray EnumTypes, MDTypeArray RetainedTypes, + MDSubprogramArray Subprograms, + MDGlobalVariableArray GlobalVariables, + MDImportedEntityArray ImportedEntities), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, @@ -820,17 +1053,32 @@ public: 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); } + MDCompositeTypeArray getEnumTypes() const { + return cast_or_null<MDTuple>(getRawEnumTypes()); + } + MDTypeArray getRetainedTypes() const { + return cast_or_null<MDTuple>(getRawRetainedTypes()); + } + MDSubprogramArray getSubprograms() const { + return cast_or_null<MDTuple>(getRawSubprograms()); + } + MDGlobalVariableArray getGlobalVariables() const { + return cast_or_null<MDTuple>(getRawGlobalVariables()); + } + MDImportedEntityArray getImportedEntities() const { + return cast_or_null<MDTuple>(getRawImportedEntities()); + } MDString *getRawProducer() const { return getOperandAs<MDString>(1); } MDString *getRawFlags() const { return getOperandAs<MDString>(2); } MDString *getRawSplitDebugFilename() const { return getOperandAs<MDString>(3); } + Metadata *getRawEnumTypes() const { return getOperand(4); } + Metadata *getRawRetainedTypes() const { return getOperand(5); } + Metadata *getRawSubprograms() const { return getOperand(6); } + Metadata *getRawGlobalVariables() const { return getOperand(7); } + Metadata *getRawImportedEntities() const { return getOperand(8); } /// \brief Replace arrays. /// @@ -838,8 +1086,12 @@ public: /// 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); } + void replaceSubprograms(MDSubprogramArray N) { + replaceOperandWith(6, N.get()); + } + void replaceGlobalVariables(MDGlobalVariableArray N) { + replaceOperandWith(7, N.get()); + } /// @} static bool classof(const Metadata *MD) { @@ -857,9 +1109,15 @@ protected: MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef<Metadata *> Ops) : MDScope(C, ID, Storage, Tag, Ops) {} - ~MDLocalScope() {} + ~MDLocalScope() = default; public: + /// \brief Get the subprogram for this scope. + /// + /// Return this if it's an \a MDSubprogram; otherwise, look up the scope + /// chain. + MDSubprogram *getSubprogram() const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubprogramKind || MD->getMetadataID() == MDLexicalBlockKind || @@ -914,12 +1172,58 @@ public: unsigned getLine() const { return SubclassData32; } unsigned getColumn() const { return SubclassData16; } MDLocalScope *getScope() const { - return cast_or_null<MDLocalScope>(getRawScope()); + return cast<MDLocalScope>(getRawScope()); } MDLocation *getInlinedAt() const { return cast_or_null<MDLocation>(getRawInlinedAt()); } + MDFile *getFile() const { return getScope()->getFile(); } + StringRef getFilename() const { return getScope()->getFilename(); } + StringRef getDirectory() const { return getScope()->getDirectory(); } + + /// \brief Get the scope where this is inlined. + /// + /// Walk through \a getInlinedAt() and return \a getScope() from the deepest + /// location. + MDLocalScope *getInlinedAtScope() const { + if (auto *IA = getInlinedAt()) + return IA->getInlinedAtScope(); + return getScope(); + } + + /// \brief Check whether this can be discriminated from another location. + /// + /// Check \c this can be discriminated from \c RHS in a linetable entry. + /// Scope and inlined-at chains are not recorded in the linetable, so they + /// cannot be used to distinguish basic blocks. + /// + /// The current implementation is weaker than it should be, since it just + /// checks filename and line. + /// + /// FIXME: Add a check for getDiscriminator(). + /// FIXME: Add a check for getColumn(). + /// FIXME: Change the getFilename() check to getFile() (or add one for + /// getDirectory()). + bool canDiscriminate(const MDLocation &RHS) const { + return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); + } + + /// \brief Get the DWARF discriminator. + /// + /// DWARF discriminators distinguish identical file locations between + /// instructions that are on different basic blocks. + inline unsigned getDiscriminator() const; + + /// \brief Compute new discriminator in the given context. + /// + /// This modifies the \a LLVMContext that \c this is in to increment the next + /// discriminator for \c this's line/filename combination. + /// + /// FIXME: Delete this. See comments in implementation and at the only call + /// site in \a AddDiscriminators::runOnFunction(). + unsigned computeNewDiscriminator() const; + Metadata *getRawScope() const { return getOperand(0); } Metadata *getRawInlinedAt() const { if (getNumOperands() == 2) @@ -958,21 +1262,23 @@ class MDSubprogram : public MDLocalScope { Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} - ~MDSubprogram() {} + ~MDSubprogram() = default; 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, + getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, + MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function, MDTemplateParameterArray TemplateParams, + MDSubprogram *Declaration, MDLocalVariableArray 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, + Virtuality, VirtualIndex, Flags, IsOptimized, + Function ? ConstantAsMetadata::get(Function) : nullptr, + TemplateParams.get(), Declaration, Variables.get(), Storage, ShouldCreate); } static MDSubprogram * @@ -989,22 +1295,25 @@ class MDSubprogram : public MDLocalScope { getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(), getContainingType(), getVirtuality(), getVirtualIndex(), getFlags(), - isOptimized(), getFunction(), getTemplateParams(), - getDeclaration(), getVariables()); + isOptimized(), getFunctionConstant(), + 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, + (MDScopeRef Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, MDSubroutineType *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + MDTypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function = nullptr, + MDTemplateParameterArray TemplateParams = nullptr, + MDSubprogram *Declaration = nullptr, + MDLocalVariableArray 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, @@ -1029,7 +1338,36 @@ public: bool isDefinition() const { return IsDefinition; } bool isOptimized() const { return IsOptimized; } - Metadata *getScope() const { return getOperand(1); } + unsigned isArtificial() const { return getFlags() & FlagArtificial; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isExplicit() const { return getFlags() & FlagExplicit; } + bool isPrototyped() const { return getFlags() & FlagPrototyped; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return getFlags() & FlagLValueReference; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return getFlags() & FlagRValueReference; + } + + MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } StringRef getDisplayName() const { return getStringOperand(3); } @@ -1038,13 +1376,42 @@ public: MDString *getRawName() const { return getOperandAs<MDString>(2); } MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); } - Metadata *getType() const { return getOperand(5); } - Metadata *getContainingType() const { return getOperand(6); } + MDSubroutineType *getType() const { + return cast_or_null<MDSubroutineType>(getRawType()); + } + MDTypeRef getContainingType() const { + return MDTypeRef(getRawContainingType()); + } - Metadata *getFunction() const { return getOperand(7); } - Metadata *getTemplateParams() const { return getOperand(8); } - Metadata *getDeclaration() const { return getOperand(9); } - Metadata *getVariables() const { return getOperand(10); } + Constant *getFunctionConstant() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction())) + return C->getValue(); + return nullptr; + } + MDTemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } + MDSubprogram *getDeclaration() const { + return cast_or_null<MDSubprogram>(getRawDeclaration()); + } + MDLocalVariableArray getVariables() const { + return cast_or_null<MDTuple>(getRawVariables()); + } + + Metadata *getRawScope() const { return getOperand(1); } + Metadata *getRawType() const { return getOperand(5); } + Metadata *getRawContainingType() const { return getOperand(6); } + Metadata *getRawFunction() const { return getOperand(7); } + Metadata *getRawTemplateParams() const { return getOperand(8); } + Metadata *getRawDeclaration() const { return getOperand(9); } + Metadata *getRawVariables() const { return getOperand(10); } + + /// \brief Get a pointer to the function this subprogram describes. + /// + /// This dyn_casts \a getFunctionConstant() to \a Function. + /// + /// FIXME: Should this be looking through bitcasts? + Function *getFunction() const; /// \brief Replace the function. /// @@ -1057,6 +1424,11 @@ public: void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } /// @} + /// \brief Check if this subprogram decribes the given function. + /// + /// FIXME: Should this be looking through bitcasts? + bool describes(const Function *F) const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubprogramKind; } @@ -1067,11 +1439,20 @@ protected: MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef<Metadata *> Ops) : MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} - ~MDLexicalBlockBase() {} + ~MDLexicalBlockBase() = default; public: - Metadata *getScope() const { return getOperand(1); } + MDLocalScope *getScope() const { return cast<MDLocalScope>(getRawScope()); } + Metadata *getRawScope() const { return getOperand(1); } + + /// \brief Forwarding accessors to LexicalBlock. + /// + /// TODO: Remove these and update code to use \a MDLexicalBlock directly. + /// @{ + inline unsigned getLine() const; + inline unsigned getColumn() const; + /// @} static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLexicalBlockKind || MD->getMetadataID() == MDLexicalBlockFileKind; @@ -1089,7 +1470,16 @@ class MDLexicalBlock : public MDLexicalBlockBase { unsigned Column, ArrayRef<Metadata *> Ops) : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), Column(Column) {} - ~MDLexicalBlock() {} + ~MDLexicalBlock() = default; + + static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Line, unsigned Column, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Line, Column, Storage, + ShouldCreate); + } static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, @@ -1101,6 +1491,9 @@ class MDLexicalBlock : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlock, (MDLocalScope * Scope, MDFile *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, unsigned Line, unsigned Column), (Scope, File, Line, Column)) @@ -1115,6 +1508,18 @@ public: } }; +unsigned MDLexicalBlockBase::getLine() const { + if (auto *N = dyn_cast<MDLexicalBlock>(this)) + return N->getLine(); + return 0; +} + +unsigned MDLexicalBlockBase::getColumn() const { + if (auto *N = dyn_cast<MDLexicalBlock>(this)) + return N->getColumn(); + return 0; +} + class MDLexicalBlockFile : public MDLexicalBlockBase { friend class LLVMContextImpl; friend class MDNode; @@ -1125,7 +1530,16 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { unsigned Discriminator, ArrayRef<Metadata *> Ops) : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), Discriminator(Discriminator) {} - ~MDLexicalBlockFile() {} + ~MDLexicalBlockFile() = default; + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Discriminator, Storage, + ShouldCreate); + } static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Discriminator, @@ -1138,12 +1552,19 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, (MDLocalScope * Scope, MDFile *File, + unsigned Discriminator), + (Scope, File, Discriminator)) DEFINE_MDNODE_GET(MDLexicalBlockFile, (Metadata * Scope, Metadata *File, unsigned Discriminator), (Scope, File, Discriminator)) TempMDLexicalBlockFile clone() const { return cloneImpl(); } + // TODO: Remove these once they're gone from MDLexicalBlockBase. + unsigned getLine() const = delete; + unsigned getColumn() const = delete; + unsigned getDiscriminator() const { return Discriminator; } static bool classof(const Metadata *MD) { @@ -1151,6 +1572,12 @@ public: } }; +unsigned MDLocation::getDiscriminator() const { + if (auto *F = dyn_cast<MDLexicalBlockFile>(getScope())) + return F->getDiscriminator(); + return 0; +} + class MDNamespace : public MDScope { friend class LLVMContextImpl; friend class MDNode; @@ -1162,10 +1589,10 @@ class MDNamespace : public MDScope { : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops), Line(Line) {} - ~MDNamespace() {} + ~MDNamespace() = default; - static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, - Metadata *File, StringRef Name, unsigned Line, + static MDNamespace *getImpl(LLVMContext &Context, MDScope *Scope, + MDFile *File, StringRef Name, unsigned Line, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), Line, Storage, ShouldCreate); @@ -1180,8 +1607,8 @@ class MDNamespace : public MDScope { } public: - DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, - StringRef Name, unsigned Line), + DEFINE_MDNODE_GET(MDNamespace, (MDScope * Scope, MDFile *File, StringRef Name, + unsigned Line), (Scope, File, Name, Line)) DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, MDString *Name, unsigned Line), @@ -1190,9 +1617,10 @@ public: TempMDNamespace clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(1); } + MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); } StringRef getName() const { return getStringOperand(2); } + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } static bool classof(const Metadata *MD) { @@ -1206,13 +1634,14 @@ protected: MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef<Metadata *> Ops) : DebugNode(Context, ID, Storage, Tag, Ops) {} - ~MDTemplateParameter() {} + ~MDTemplateParameter() = default; public: StringRef getName() const { return getStringOperand(0); } - Metadata *getType() const { return getOperand(1); } + MDTypeRef getType() const { return MDTypeRef(getRawType()); } MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawType() const { return getOperand(1); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDTemplateTypeParameterKind || @@ -1228,10 +1657,10 @@ class MDTemplateTypeParameter : public MDTemplateParameter { ArrayRef<Metadata *> Ops) : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, dwarf::DW_TAG_template_type_parameter, Ops) {} - ~MDTemplateTypeParameter() {} + ~MDTemplateTypeParameter() = default; static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, - Metadata *Type, StorageType Storage, + MDTypeRef Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, ShouldCreate); @@ -1245,7 +1674,7 @@ class MDTemplateTypeParameter : public MDTemplateParameter { } public: - DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, MDTypeRef Type), (Name, Type)) DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), (Name, Type)) @@ -1265,10 +1694,10 @@ class MDTemplateValueParameter : public MDTemplateParameter { unsigned Tag, ArrayRef<Metadata *> Ops) : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, Ops) {} - ~MDTemplateValueParameter() {} + ~MDTemplateValueParameter() = default; static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *Type, + StringRef Name, MDTypeRef Type, Metadata *Value, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, @@ -1286,7 +1715,7 @@ class MDTemplateValueParameter : public MDTemplateParameter { public: DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, - Metadata *Type, Metadata *Value), + MDTypeRef Type, Metadata *Value), (Tag, Name, Type, Value)) DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value), @@ -1311,16 +1740,30 @@ protected: MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef<Metadata *> Ops) : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} - ~MDVariable() {} + ~MDVariable() = default; public: unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } + MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); } StringRef getName() const { return getStringOperand(1); } - Metadata *getFile() const { return getOperand(2); } - Metadata *getType() const { return getOperand(3); } + MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); } + MDTypeRef getType() const { return MDTypeRef(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + Metadata *getRawScope() const { return getOperand(0); } MDString *getRawName() const { return getOperandAs<MDString>(1); } + Metadata *getRawFile() const { return getOperand(2); } + Metadata *getRawType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind || @@ -1344,17 +1787,18 @@ class MDGlobalVariable : public MDVariable { : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, Line, Ops), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} - ~MDGlobalVariable() {} + ~MDGlobalVariable() = default; 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, + getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + MDDerivedType *StaticDataMemberDeclaration, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, - IsLocalToUnit, IsDefinition, Variable, + IsLocalToUnit, IsDefinition, + Variable ? ConstantAsMetadata::get(Variable) : nullptr, StaticDataMemberDeclaration, Storage, ShouldCreate); } static MDGlobalVariable * @@ -1373,10 +1817,10 @@ class MDGlobalVariable : public MDVariable { 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), + (MDScope * Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, MDTypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + MDDerivedType *StaticDataMemberDeclaration), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)) DEFINE_MDNODE_GET(MDGlobalVariable, @@ -1393,10 +1837,18 @@ public: 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); } + Constant *getVariable() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable())) + return dyn_cast<Constant>(C->getValue()); + return nullptr; + } + MDDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null<MDDerivedType>(getRawStaticDataMemberDeclaration()); + } MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } + Metadata *getRawVariable() const { return getOperand(6); } + Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDGlobalVariableKind; @@ -1420,62 +1872,61 @@ class MDLocalVariable : public MDVariable { ArrayRef<Metadata *> Ops) : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), Flags(Flags) {} - ~MDLocalVariable() {} + ~MDLocalVariable() = default; 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, + MDScope *Scope, StringRef Name, MDFile *File, + unsigned Line, MDTypeRef Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), - File, Line, Type, Arg, Flags, InlinedAt, Storage, - ShouldCreate); + File, Line, Type, Arg, Flags, 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); + static MDLocalVariable * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true); TempMDLocalVariable cloneImpl() const { return getTemporary(getContext(), getTag(), getScope(), getName(), - getFile(), getLine(), getType(), getArg(), getFlags(), - getInlinedAt()); + getFile(), getLine(), getType(), getArg(), getFlags()); } 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)) + (unsigned Tag, MDLocalScope *Scope, StringRef Name, + MDFile *File, unsigned Line, MDTypeRef Type, unsigned Arg, + unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) 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)) + unsigned Arg, unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) TempMDLocalVariable clone() const { return cloneImpl(); } + /// \brief Get the local scope for this variable. + /// + /// Variables must be defined in a local scope. + MDLocalScope *getScope() const { + return cast<MDLocalScope>(MDVariable::getScope()); + } + unsigned getArg() const { return Arg; } unsigned getFlags() const { return Flags; } - Metadata *getInlinedAt() const { return getOperand(4); } - /// \brief Get an inlined version of this variable. + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + + /// \brief Check that a location is valid for this variable. /// - /// Returns a version of this with \a getAlinedAt() set to \c InlinedAt. - MDLocalVariable *withInline(MDLocation *InlinedAt) const { - if (InlinedAt == getInlinedAt()) - return const_cast<MDLocalVariable *>(this); - auto Temp = clone(); - Temp->replaceOperandWith(4, InlinedAt); - return replaceWithUniqued(std::move(Temp)); + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const MDLocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); } - MDLocalVariable *withoutInline() const { return withInline(nullptr); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind; @@ -1484,6 +1935,12 @@ public: /// \brief DWARF expression. /// +/// 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. +/// /// TODO: Co-allocate the expression elements. /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary /// storage types. @@ -1496,7 +1953,7 @@ class MDExpression : public MDNode { MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) : MDNode(C, MDExpressionKind, Storage, None), Elements(Elements.begin(), Elements.end()) {} - ~MDExpression() {} + ~MDExpression() = default; static MDExpression *getImpl(LLVMContext &Context, ArrayRef<uint64_t> Elements, StorageType Storage, @@ -1519,6 +1976,15 @@ public: return Elements[I]; } + /// \brief Return whether this is a piece of an aggregate variable. + 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; + typedef ArrayRef<uint64_t>::iterator element_iterator; element_iterator elements_begin() const { return getElements().begin(); } element_iterator elements_end() const { return getElements().end(); } @@ -1573,6 +2039,13 @@ public: return T; } + /// \brief Get the next iterator. + /// + /// \a std::next() doesn't work because this is technically an + /// input_iterator, but it's a perfectly valid operation. This is an + /// accessor to provide the same functionality. + expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } + bool operator==(const expr_op_iterator &X) const { return getBase() == X.getBase(); } @@ -1619,12 +2092,12 @@ class MDObjCProperty : public DebugNode { : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops), Line(Line), Attributes(Attributes) {} - ~MDObjCProperty() {} + ~MDObjCProperty() = default; static MDObjCProperty * - getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + getImpl(LLVMContext &Context, StringRef Name, MDFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, unsigned Attributes, - Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + MDType *Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, getCanonicalMDString(Context, GetterName), getCanonicalMDString(Context, SetterName), Attributes, Type, @@ -1644,9 +2117,9 @@ class MDObjCProperty : public DebugNode { public: DEFINE_MDNODE_GET(MDObjCProperty, - (StringRef Name, Metadata *File, unsigned Line, + (StringRef Name, MDFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, - unsigned Attributes, Metadata *Type), + unsigned Attributes, MDType *Type), (Name, File, Line, GetterName, SetterName, Attributes, Type)) DEFINE_MDNODE_GET(MDObjCProperty, @@ -1661,20 +2134,39 @@ public: unsigned getLine() const { return Line; } unsigned getAttributes() const { return Attributes; } StringRef getName() const { return getStringOperand(0); } - Metadata *getFile() const { return getOperand(1); } + MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); } StringRef getGetterName() const { return getStringOperand(2); } StringRef getSetterName() const { return getStringOperand(3); } - Metadata *getType() const { return getOperand(4); } + + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing + /// the type as a DITypeRef here. + MDType *getType() const { return cast_or_null<MDType>(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawFile() const { return getOperand(1); } MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } + Metadata *getRawType() const { return getOperand(4); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDObjCPropertyKind; } }; +/// \brief An imported module (C++ using directive or similar). class MDImportedEntity : public DebugNode { friend class LLVMContextImpl; friend class MDNode; @@ -1684,10 +2176,10 @@ class MDImportedEntity : public DebugNode { MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef<Metadata *> Ops) : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} - ~MDImportedEntity() {} + ~MDImportedEntity() = default; static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, Metadata *Entity, + MDScope *Scope, DebugNodeRef Entity, unsigned Line, StringRef Name, StorageType Storage, bool ShouldCreate = true) { @@ -1707,7 +2199,7 @@ class MDImportedEntity : public DebugNode { public: DEFINE_MDNODE_GET(MDImportedEntity, - (unsigned Tag, Metadata *Scope, Metadata *Entity, + (unsigned Tag, MDScope *Scope, DebugNodeRef Entity, unsigned Line, StringRef Name = ""), (Tag, Scope, Entity, Line, Name)) DEFINE_MDNODE_GET(MDImportedEntity, @@ -1718,10 +2210,12 @@ public: TempMDImportedEntity clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } - Metadata *getEntity() const { return getOperand(1); } + MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); } + DebugNodeRef getEntity() const { return DebugNodeRef(getRawEntity()); } StringRef getName() const { return getStringOperand(2); } + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawEntity() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } static bool classof(const Metadata *MD) { diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index c29d5bf..f88a7b1 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -22,11 +22,15 @@ namespace llvm { 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 MDLocation; + + /// \brief A debug info location. + /// + /// This class is a wrapper around a tracking reference to an \a MDLocation + /// pointer. + /// + /// To avoid extra includes, \a DebugLoc doubles the \a MDLocation API with a + /// one based on relatively opaque \a MDNode pointers. class DebugLoc { TrackingMDNodeRef Loc; @@ -43,64 +47,76 @@ namespace llvm { return *this; } + /// \brief Construct from an \a MDLocation. + DebugLoc(const MDLocation *L); + + /// \brief Construct from an \a MDNode. + /// + /// Note: if \c N is not an \a MDLocation, a verifier check will fail, and + /// accessors will crash. However, construction from other nodes is + /// supported in order to handle forward references when reading textual + /// IR. + explicit DebugLoc(const MDNode *N); + + /// \brief Get the underlying \a MDLocation. + /// + /// \pre !*this or \c isa<MDLocation>(getAsMDNode()). + /// @{ + MDLocation *get() const; + operator MDLocation *() const { return get(); } + MDLocation *operator->() const { return get(); } + MDLocation &operator*() const { return *get(); } + /// @} + + /// \brief Check for null. + /// + /// Check for null in a way that is safe with broken debug info. Unlike + /// the conversion to \c MDLocation, this doesn't require that \c Loc is of + /// the right type. Important for cases like \a llvm::StripDebugInfo() and + /// \a Instruction::hasMetadata(). + explicit operator bool() const { return Loc; } + /// \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); - - /// getFromDILocation - Translate the DILocation quad into a DebugLoc. - static DebugLoc getFromDILocation(MDNode *N); - - /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. - static DebugLoc getFromDILexicalBlock(MDNode *N); - - /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return !Loc; } + /// \brief Create a new DebugLoc. + /// + /// Create a new DebugLoc at the specified line/col and scope/inline. This + /// forwards to \a MDLocation::get(). + /// + /// If \c !Scope, returns a default-constructed \a DebugLoc. + /// + /// FIXME: Remove this. Users should use MDLocation::get(). + static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, + const MDNode *InlinedAt = nullptr); unsigned getLine() const; unsigned getCol() const; - - /// getScope - This returns the scope pointer for this DebugLoc, or null if - /// invalid. 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; - 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 &) const { - return getScopeAndInlinedAt(Scope, IA); - } - - /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - 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. + MDLocation *getInlinedAt() const; + + /// \brief Get the fully inlined-at scope for a DebugLoc. + /// + /// Gets the inlined-at scope for a DebugLoc. + MDNode *getInlinedAtScope() const; + + /// \brief Find the debug info location for the start of the function. + /// + /// Walk up the scope chain of given debug loc and find line number info + /// for the function. + /// + /// FIXME: Remove this. Users should use MDLocation/MDLocalScope API to + /// find the subprogram, and then MDLocation::get(). 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; - MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } + /// \brief Return \c this as a bar \a MDNode. + MDNode *getAsMDNode() const { return Loc; } bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } - bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } + bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } void dump() const; - void dump(const LLVMContext &) const { dump(); } + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] void print(raw_ostream &OS) const; }; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 0cd5afb..a5eed9b 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -31,26 +31,6 @@ namespace llvm { class FunctionType; class LLVMContext; -// Traits for intrusive list of basic blocks... -template<> struct ilist_traits<BasicBlock> - : public SymbolTableListTraits<BasicBlock, Function> { - - // createSentinel is used to get hold of the node that marks the end of the - // list... (same trick used here as in ilist_traits<Instruction>) - BasicBlock *createSentinel() const { - return static_cast<BasicBlock*>(&Sentinel); - } - static void destroySentinel(BasicBlock*) {} - - BasicBlock *provideInitialHead() const { return createSentinel(); } - BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } - static void noteHead(BasicBlock*, BasicBlock*) {} - - static ValueSymbolTable *getSymTab(Function *ItemParent); -private: - mutable ilist_half_node<BasicBlock> Sentinel; -}; - template<> struct ilist_traits<Argument> : public SymbolTableListTraits<Argument, Function> { @@ -86,6 +66,7 @@ private: mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes + FunctionType *Ty; /* * Value::SubclassData @@ -133,7 +114,7 @@ public: return new(0) Function(Ty, Linkage, N, M); } - ~Function(); + ~Function() override; Type *getReturnType() const; // Return the type of the ret val FunctionType *getFunctionType() const; // Return the FunctionType for me @@ -242,6 +223,10 @@ public: /// @brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// @brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(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); @@ -472,6 +457,10 @@ public: Constant *getPrologueData() const; void setPrologueData(Constant *PrologueData); + /// Print the function to an output stream with an optional + /// AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr) const; + /// 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 ae2f2e1..779f2e0 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -54,6 +54,7 @@ public: virtual std::error_code MaterializeModule(Module *M) = 0; virtual std::error_code materializeMetadata() = 0; + virtual void setStripDebugInfo() = 0; virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0; }; diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 50deb08..f055241 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -27,7 +27,7 @@ class GlobalObject : public GlobalValue { GlobalObject(const GlobalObject &) = delete; protected: - GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalObject(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) { setGlobalValueSubClassData(0); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 002e5e7..aeaaef4 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -61,7 +61,7 @@ public: }; protected: - GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalValue(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), @@ -104,7 +104,7 @@ public: LocalExecTLSModel }; - ~GlobalValue() { + ~GlobalValue() override { removeDeadConstantUsers(); // remove any dead constants using this. } @@ -165,9 +165,9 @@ public: const char *getSection() const; /// Global values are always pointers. - inline PointerType *getType() const { - return cast<PointerType>(User::getType()); - } + PointerType *getType() const { return cast<PointerType>(User::getType()); } + + Type *getValueType() const { return getType()->getElementType(); } static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; @@ -343,11 +343,11 @@ public: virtual void eraseFromParent() = 0; /// Get the module that this global value is contained inside of... - inline Module *getParent() { return Parent; } - inline const Module *getParent() const { return Parent; } + Module *getParent() { return Parent; } + const Module *getParent() const { return Parent; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Value *V) { + static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || V->getValueID() == Value::GlobalAliasVal; diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index d7b81a2..9f57705 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -66,7 +66,7 @@ public: ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, bool isExternallyInitialized = false); - ~GlobalVariable() { + ~GlobalVariable() override { NumOperands = 1; // FIXME: needed by operator delete } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 617e2bc..9c4ba07 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -21,6 +21,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" @@ -123,7 +124,7 @@ public: /// \brief If this builder has a current debug location, set it on the /// specified instruction. void SetInstDebugLocation(Instruction *I) const { - if (!CurDbgLocation.isUnknown()) + if (CurDbgLocation) I->setDebugLoc(CurDbgLocation); } @@ -243,7 +244,7 @@ public: /// filled in with the null terminated string value specified. The new global /// variable will be marked mergable with any others of the same contents. If /// Name is specified, it is the name of the global variable created. - Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); + GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = ""); /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -1028,12 +1029,16 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IdxList), Name); } return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; @@ -1041,68 +1046,77 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IdxList), + Name); } - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, IdxList), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, Idx, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name); + } + Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, + const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } - Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, + unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name); return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } @@ -1111,7 +1125,7 @@ public: Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name); return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } @@ -1123,7 +1137,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name); return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } @@ -1135,21 +1149,23 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs), + Name); return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, + const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type /// instead of a pointer to array of i8. Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - Value *gv = CreateGlobalString(Str, Name); + GlobalVariable *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Name); + return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 7f2027b..5f1d56f 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -34,7 +34,8 @@ class raw_ostream; /// \brief Create and return a pass that writes the module to the specified /// \c raw_ostream. ModulePass *createPrintModulePass(raw_ostream &OS, - const std::string &Banner = ""); + const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); /// \brief Create and return a pass that prints functions to the specified /// \c raw_ostream as they are processed. @@ -53,10 +54,12 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, class PrintModulePass { raw_ostream &OS; std::string Banner; + bool ShouldPreserveUseListOrder; public: PrintModulePass(); - PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); + PrintModulePass(raw_ostream &OS, const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); PreservedAnalyses run(Module &M); diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 6ae4122..c8f25e7 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -51,7 +51,7 @@ private: InlineAsm(PointerType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, bool isAlignStack, AsmDialect asmDialect); - virtual ~InlineAsm(); + ~InlineAsm() override; /// When the ConstantUniqueMap merges two types and makes two InlineAsms /// identical, it destroys one of them with this method. diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 3a33f43..108b9eb 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -44,7 +44,7 @@ protected: : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} // Out of line virtual method, so the vtable, etc has a home. - ~TerminatorInst(); + ~TerminatorInst() override; /// Virtual methods - Terminators should overload these and provide inline /// overrides of non-V methods. @@ -102,7 +102,7 @@ public: } // Out of line virtual method, so the vtable, etc has a home. - ~UnaryInstruction(); + ~UnaryInstruction() override; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index dc96b57..9dd16fd 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ilist_node.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/User.h" namespace llvm { @@ -25,10 +26,27 @@ namespace llvm { class FastMathFlags; class LLVMContext; class MDNode; +class BasicBlock; struct AAMDNodes; -template<typename ValueSubClass, typename ItemParentClass> - class SymbolTableListTraits; +template <> +struct ilist_traits<Instruction> + : public SymbolTableListTraits<Instruction, BasicBlock> { + + /// \brief Return a node that marks the end of a list. + /// + /// The sentinel is relative to this instance, so we use a non-static + /// method. + Instruction *createSentinel() const; + static void destroySentinel(Instruction *) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction *) const { return createSentinel(); } + static void noteHead(Instruction *, Instruction *) {} + +private: + mutable ilist_half_node<Instruction> Sentinel; +}; class Instruction : public User, public ilist_node<Instruction> { void operator=(const Instruction &) = delete; @@ -44,7 +62,7 @@ class Instruction : public User, public ilist_node<Instruction> { }; public: // Out of line virtual method, so the vtable, etc has a home. - ~Instruction(); + ~Instruction() override; /// user_back - Specialize the methods defined in Value, as we know that an /// instruction can only be used by other instructions. @@ -69,7 +87,8 @@ public: /// eraseFromParent - This method unlinks 'this' from the containing basic /// block and deletes it. /// - void eraseFromParent(); + /// \returns an iterator pointing to the element after the erased one + iplist<Instruction>::iterator eraseFromParent(); /// insertBefore - Insert an unlinked instructions into a basic block /// immediately before the specified instruction. @@ -134,9 +153,7 @@ public: /// hasMetadata() - Return true if this instruction has any metadata attached /// to it. - bool hasMetadata() const { - return !DbgLoc.isUnknown() || hasMetadataHashEntry(); - } + bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); } /// hasMetadataOtherThanDebugLoc - Return true if this instruction has /// metadata attached to it other than a debug location. @@ -495,6 +512,17 @@ protected: }; +inline Instruction *ilist_traits<Instruction>::createSentinel() const { + // Since i(p)lists always publicly derive from their corresponding traits, + // placing a data member in this class will augment the i(p)list. But since + // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, + // there is a legal viable downcast from it to NodeTy. We use this trick to + // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the + // sentinel. Dereferencing the sentinel is forbidden (save the + // ilist_node<NodeTy>), so no one will ever notice the superposition. + return static_cast<Instruction *>(&Sentinel); +} + // Instruction* is only 4-byte aligned. template<> class PointerLikeTypeTraits<Instruction*> { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 52fa360..1f2ca30 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -91,7 +91,7 @@ public: const Twine &Name, BasicBlock *InsertAtEnd); // Out of line virtual method, so the vtable, etc. has a home. - virtual ~AllocaInst(); + ~AllocaInst() override; /// isArrayAllocation - Return true if there is an allocation size parameter /// to the allocation instruction that is not 1. @@ -180,7 +180,12 @@ public: unsigned Align, Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, Order, SynchScope, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, Instruction *InsertBefore = nullptr); @@ -882,9 +887,9 @@ public: /// Null is returned if the indices are invalid for the specified /// pointer type. /// - static Type *getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Value *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Constant *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList); inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } @@ -915,9 +920,12 @@ public: /// GetGEPReturnType - Returns the pointer type returned by the GEP /// instruction, which may be a vector of pointers. static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) { - Type *PtrTy = PointerType::get(checkGEPType( - getIndexedType(Ptr->getType(), IdxList)), - Ptr->getType()->getPointerAddressSpace()); + Type *PtrTy = + PointerType::get(checkGEPType(getIndexedType( + cast<PointerType>(Ptr->getType()->getScalarType()) + ->getElementType(), + IdxList)), + Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { unsigned NumElem = cast<VectorType>(Ptr->getType())->getNumElements(); @@ -1327,7 +1335,11 @@ public: static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); - ~CallInst(); + ~CallInst() override; + + Type *getFunctionType() const { + return cast<PointerType>(getCalledValue()->getType())->getElementType(); + } // Note that 'musttail' implies 'tail'. enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; @@ -1404,6 +1416,10 @@ public: /// \brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -2167,7 +2183,7 @@ public: const Twine &NameStr, BasicBlock *InsertAtEnd) { return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } - ~PHINode(); + ~PHINode() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2358,7 +2374,7 @@ public: static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd); - ~LandingPadInst(); + ~LandingPadInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2460,7 +2476,7 @@ public: static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { return new(0) ReturnInst(C, InsertAtEnd); } - virtual ~ReturnInst(); + ~ReturnInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2757,7 +2773,7 @@ public: return new SwitchInst(Value, Default, NumCases, InsertAtEnd); } - ~SwitchInst(); + ~SwitchInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2943,7 +2959,7 @@ public: BasicBlock *InsertAtEnd) { return new IndirectBrInst(Address, NumDests, InsertAtEnd); } - ~IndirectBrInst(); + ~IndirectBrInst() override; /// Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -3093,9 +3109,13 @@ 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. + /// \brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index da9d8cb..4052a31 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -421,10 +421,6 @@ def int_eh_endcatch : Intrinsic<[], []>; // Represents the list of actions to take when an exception is thrown. def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; -// Designates the provided static alloca as the unwind help object. Required -// for WinEH. -def int_eh_unwindhelp : Intrinsic<[], [llvm_ptr_ty], []>; - // __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. @@ -630,3 +626,4 @@ include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" include "llvm/IR/IntrinsicsBPF.td" +include "llvm/IR/IntrinsicsSystemZ.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td index 6b5110b..94eca8e 100644 --- a/include/llvm/IR/IntrinsicsBPF.td +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -19,4 +19,6 @@ let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." 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]>; + def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>; } diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 95fc3e5..74c0172 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -37,6 +37,25 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // generated by the PowerPC backend! def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; + + // Intrinsics for [double]word extended forms of divide instructions + def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divweu : GCCBuiltin<"__builtin_divweu">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divde : GCCBuiltin<"__builtin_divde">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_ppc_divdeu : GCCBuiltin<"__builtin_divdeu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + + // Bit permute doubleword + def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; } @@ -563,11 +582,12 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -// These need diagnostics for invalid arguments so don't inherit from GCCBuiltin def int_ppc_altivec_crypto_vshasigmad : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_ppc_altivec_crypto_vshasigmaw : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; } @@ -801,20 +821,20 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". -def int_ppc_tbegin : +def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -def int_ppc_tend : +def int_ppc_tend : GCCBuiltin<"__builtin_tend">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -def int_ppc_tabortwc : +def int_ppc_tabortwc : GCCBuiltin<"__builtin_tabortwc">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortwci : +def int_ppc_tabortwci : GCCBuiltin<"__builtin_tabortwci">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortdc : +def int_ppc_tabortdc : GCCBuiltin<"__builtin_tabortdc">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortdci : +def int_ppc_tabortdci : GCCBuiltin<"__builtin_tabortdci">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">, @@ -823,7 +843,7 @@ def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">, Intrinsic<[llvm_i32_ty], [], []>; -def int_ppc_tsr : +def int_ppc_tsr : GCCBuiltin<"__builtin_tsr">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">, diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td new file mode 100644 index 0000000..6883db3 --- /dev/null +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -0,0 +1,46 @@ +//===- IntrinsicsSystemZ.td - Defines SystemZ 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 SystemZ-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// Transactional-execution intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], + [IntrNoReturn, Throws]>; + + def int_s390_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], []>; + + def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; + + def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], + [IntrReadWriteArgMem]>; + + def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, + Intrinsic<[], [llvm_i32_ty]>; +} + diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 39b8e3b..49231d8 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -1408,12 +1408,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector min, max @@ -3093,7 +3087,27 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; } - +//Bitwise Ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; +} // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". @@ -3222,6 +3236,27 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } +// Integer arithmetic ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_padd_d_512 : GCCBuiltin<"__builtin_ia32_paddd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_512 : GCCBuiltin<"__builtin_ia32_paddq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_512 : GCCBuiltin<"__builtin_ia32_psubd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_512 : GCCBuiltin<"__builtin_ia32_psubq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; +} // Gather and Scatter ops let TargetPrefix = "x86" in { def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, @@ -3813,14 +3848,6 @@ let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, 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, - llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index 6c04e9d..5257a0e 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -50,7 +50,7 @@ class PassManager : public PassManagerBase { public: PassManager(); - ~PassManager(); + ~PassManager() override; void add(Pass *P) override; @@ -70,7 +70,7 @@ public: /// FunctionPassManager ctor - This initializes the pass manager. It needs, /// but does not take ownership of, the specified Module. explicit FunctionPassManager(Module *M); - ~FunctionPassManager(); + ~FunctionPassManager() override; void add(Pass *P) override; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index 52db1c3..39ae80d 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -43,7 +43,7 @@ class PassNameParser : public PassRegistrationListener, public cl::parser<const PassInfo*> { public: PassNameParser(cl::Option &O); - virtual ~PassNameParser(); + ~PassNameParser() override; void initialize() { cl::parser<const PassInfo*>::initialize(); diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index a31bdbf..03e70fe 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -89,7 +89,7 @@ protected: Metadata(unsigned ID, StorageType Storage) : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { } - ~Metadata() {} + ~Metadata() = default; /// \brief Default handling of a changed operand, which asserts. /// @@ -164,7 +164,7 @@ class MetadataAsValue : public Value { Metadata *MD; MetadataAsValue(Type *Ty, Metadata *MD); - ~MetadataAsValue(); + ~MetadataAsValue() override; /// \brief Drop use of metadata (during teardown). void dropUse() { MD = nullptr; } @@ -253,7 +253,7 @@ protected: : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { assert(V && "Expected valid value"); } - ~ValueAsMetadata() {} + ~ValueAsMetadata() = default; public: static ValueAsMetadata *get(Value *V); @@ -754,13 +754,18 @@ protected: MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None); - ~MDNode() {} + ~MDNode() = default; void dropAllReferences(); MDOperand *mutable_begin() { return mutable_end() - NumOperands; } MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); } + typedef iterator_range<MDOperand *> mutable_op_range; + mutable_op_range mutable_operands() { + return mutable_op_range(mutable_begin(), mutable_end()); + } + public: static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); static inline MDTuple *getIfExists(LLVMContext &Context, @@ -1028,6 +1033,78 @@ void TempMDNodeDeleter::operator()(MDNode *Node) const { MDNode::deleteTemporary(Node); } +/// \brief Typed iterator through MDNode operands. +/// +/// An iterator that transforms an \a MDNode::iterator into an iterator over a +/// particular Metadata subclass. +template <class T> +class TypedMDOperandIterator + : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> { + MDNode::op_iterator I = nullptr; + +public: + TypedMDOperandIterator() = default; + explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {} + T *operator*() const { return cast_or_null<T>(*I); } + TypedMDOperandIterator &operator++() { + ++I; + return *this; + } + TypedMDOperandIterator operator++(int) { + TypedMDOperandIterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; } + bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } +}; + +/// \brief Typed, array-like tuple of metadata. +/// +/// This is a wrapper for \a MDTuple that makes it act like an array holding a +/// particular type of metadata. +template <class T> class MDTupleTypedArrayWrapper { + const MDTuple *N = nullptr; + +public: + MDTupleTypedArrayWrapper() = default; + MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {} + + template <class U> + MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + template <class U> + explicit MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); } + + // FIXME: Fix callers and remove condition on N. + typedef TypedMDOperandIterator<T> iterator; + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + +#define HANDLE_METADATA(CLASS) \ + typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array; +#include "llvm/IR/Metadata.def" + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index ac60c8e..dbaf322 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -642,8 +642,11 @@ public: /// @{ /// Print the module to an output stream with an optional - /// AssemblyAnnotationWriter. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include + /// uselistorder directives so that use-lists can be recreated when reading + /// the assembly. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false) const; /// Dump the module to stderr (for debugging). void dump() const; diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h index ab7bed6..61f4817 100644 --- a/include/llvm/IR/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -177,34 +177,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Instruction *CreateGetElementPtr(Constant *C, + Instruction *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::Create(nullptr, C, IdxList); + return GetElementPtrInst::Create(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Instruction *CreateInBoundsGetElementPtr(Constant *C, + Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::CreateInBounds(nullptr, C, IdxList); + return GetElementPtrInst::CreateInBounds(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index c87f89c..8c3afdd 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -42,7 +42,7 @@ protected: // 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(); + ~Operator() override; public: /// Return the opcode for this Instruction or ConstantExpr. @@ -181,17 +181,17 @@ public: { } /// Whether any flag is set - bool any() { return Flags != 0; } + bool any() const { return Flags != 0; } /// Set all the flags to false void clear() { Flags = 0; } /// Flag queries - bool noNaNs() { return 0 != (Flags & NoNaNs); } - bool noInfs() { return 0 != (Flags & NoInfs); } - bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); } - bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); } - bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); } + bool noNaNs() const { return 0 != (Flags & NoNaNs); } + bool noInfs() const { return 0 != (Flags & NoInfs); } + bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } + bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } + bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); } /// Flag setters void setNoNaNs() { Flags |= NoNaNs; } diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index f94e105..41154e6 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -295,6 +295,9 @@ template <typename Class> struct bind_ty { /// \brief Match a value, capturing it if we match. inline bind_ty<Value> m_Value(Value *&V) { return V; } +/// \brief Match an instruction, capturing it if we match. +inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; } + /// \brief Match a binary operator, capturing it if we match. inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; } @@ -1103,6 +1106,52 @@ m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); } +//===----------------------------------------------------------------------===// +// Matchers for overflow check patterns: e.g. (a + b) u< a +// + +template <typename LHS_t, typename RHS_t, typename Sum_t> +struct UAddWithOverflow_match { + LHS_t L; + RHS_t R; + Sum_t S; + + UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S) + : L(L), R(R), S(S) {} + + template <typename OpTy> bool match(OpTy *V) { + Value *ICmpLHS, *ICmpRHS; + ICmpInst::Predicate Pred; + if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) + return false; + + Value *AddLHS, *AddRHS; + auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS)); + + // (a + b) u< a, (a + b) u< b + if (Pred == ICmpInst::ICMP_ULT) + if (AddExpr.match(ICmpLHS) && (ICmpRHS == AddLHS || ICmpRHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); + + // a >u (a + b), b >u (a + b) + if (Pred == ICmpInst::ICMP_UGT) + if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); + + return false; + } +}; + +/// \brief Match an icmp instruction checking for unsigned overflow on addition. +/// +/// S is matched to the addition whose result is being checked for overflow, and +/// L and R are matched to the LHS and RHS of S. +template <typename LHS_t, typename RHS_t, typename Sum_t> +UAddWithOverflow_match<LHS_t, RHS_t, Sum_t> +m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { + return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S); +} + /// \brief Match an 'unordered' floating point minimum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index c2073c7..09b6388 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -91,8 +91,8 @@ protected: NumContainedTys(0), ContainedTys(nullptr) { setTypeID(tid); } - ~Type() {} - + ~Type() = default; + void setTypeID(TypeID ID) { IDAndSubclassData = (ID & 0xFF) | (IDAndSubclassData & 0xFFFFFF00); assert(getTypeID() == ID && "TypeID data too large for field"); diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 7d8205d..b7c2418 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -51,12 +51,6 @@ private: typedef std::vector<UseListOrder> UseListOrderStack; -/// \brief Whether to preserve use-list ordering. -bool shouldPreserveBitcodeUseListOrder(); -bool shouldPreserveAssemblyUseListOrder(); -void setPreserveBitcodeUseListOrder(bool ShouldPreserve); -void setPreserveAssemblyUseListOrder(bool ShouldPreserve); - } // end namespace llvm #endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index d39378d..4559005 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -60,9 +60,7 @@ protected: NumOperands = 0; } public: - ~User() { - Use::zap(OperandList, OperandList + NumOperands); - } + ~User() override { Use::zap(OperandList, OperandList + NumOperands); } /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); /// \brief Placement delete - required by std, but never called. diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index 08d6d17..4d00b63 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -99,8 +99,6 @@ public: explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data(Data) {} - ~ValueMap() {} - bool hasMD() const { return MDMap; } MDMapT &MD() { if (!MDMap) @@ -149,9 +147,14 @@ public: // If the key is already in the map, it returns false and doesn't update the // value. std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { - std::pair<typename MapT::iterator, bool> map_result= - Map.insert(std::make_pair(Wrap(KV.first), KV.second)); - return std::make_pair(iterator(map_result.first), map_result.second); + auto MapResult = Map.insert(std::make_pair(Wrap(KV.first), KV.second)); + return std::make_pair(iterator(MapResult.first), MapResult.second); + } + + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + auto MapResult = + Map.insert(std::make_pair(Wrap(KV.first), std::move(KV.second))); + return std::make_pair(iterator(MapResult.first), MapResult.second); } /// insert - Range insertion of pairs. @@ -258,9 +261,9 @@ public: // I could == Copy.Map->Map.end() if the onRAUW callback already // removed the old mapping. if (I != Copy.Map->Map.end()) { - ValueT Target(I->second); + ValueT Target(std::move(I->second)); Copy.Map->Map.erase(I); // Definitely destroys *this. - Copy.Map->insert(std::make_pair(typed_new_key, Target)); + Copy.Map->insert(std::make_pair(typed_new_key, std::move(Target))); } } } |