diff options
author | Pirama Arumuga Nainar <pirama@google.com> | 2015-04-08 08:55:49 -0700 |
---|---|---|
committer | Pirama Arumuga Nainar <pirama@google.com> | 2015-04-09 15:04:38 -0700 |
commit | 4c5e43da7792f75567b693105cc53e3f1992ad98 (patch) | |
tree | 1b2c9792582e12f5af0b1512e3094425f0dc0df9 /include/llvm/IR | |
parent | c75239e6119d0f9a74c57099d91cbc9bde56bf33 (diff) | |
download | external_llvm-4c5e43da7792f75567b693105cc53e3f1992ad98.zip external_llvm-4c5e43da7792f75567b693105cc53e3f1992ad98.tar.gz external_llvm-4c5e43da7792f75567b693105cc53e3f1992ad98.tar.bz2 |
Update aosp/master llvm for rebase to r233350
Change-Id: I07d935f8793ee8ec6b7da003f6483046594bca49
Diffstat (limited to 'include/llvm/IR')
31 files changed, 1282 insertions, 539 deletions
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 185fc29..8f5cdeb 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -119,7 +119,11 @@ public: const Function *getParent() const { return Parent; } Function *getParent() { return Parent; } - const DataLayout *getDataLayout() const; + /// \brief Return the module owning the function this basic block belongs to, + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the block does not have a parent. + const Module *getModule() const; /// \brief Returns the terminator instruction if the block is well formed or /// null if the block is not well formed. diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index 8476431..f78220a 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -121,7 +121,7 @@ public: typedef typename super::reference reference; private: - const Term_ Term; + Term_ Term; unsigned idx; typedef SuccIterator<Term_, BB_> Self; @@ -136,6 +136,8 @@ private: public: explicit SuccessorProxy(const Self &it) : it(it) {} + SuccessorProxy(const SuccessorProxy&) = default; + SuccessorProxy &operator=(SuccessorProxy r) { *this = reference(r); return *this; @@ -165,12 +167,6 @@ public: idx = 0; } - inline const Self &operator=(const Self &I) { - assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); - idx = I.idx; - return *this; - } - /// getSuccessorIndex - This is used to interface between code that wants to /// operate on terminator instructions directly. unsigned getSuccessorIndex() const { return idx; } diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index a4ea243..9c87936 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -151,7 +151,7 @@ public: IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } - + /// getType - Return the type of the instruction that generated this call site /// Type *getType() const { return (*this)->getType(); } diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 5e8cd34..9ded3ca 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -33,6 +33,7 @@ #define LLVM_IR_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -59,15 +60,27 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// Produce the smallest range that contains all values that - /// might satisfy the comparison specified by Pred when compared to any value - /// contained within Other. + /// Produce the smallest range such that all values that may satisfy the given + /// predicate with any value contained within Other is contained in the + /// returned range. Formally, this returns a superset of + /// 'union over all y in Other . { x : icmp op x y is true }'. If the exact + /// answer is not representable as a ConstantRange, the return value will be a + /// proper superset of the above. /// - /// Solves for range X in 'for all x in X, there exists a y in Y such that - /// icmp op x, y is true'. Every value that might make the comparison true - /// is included in the resulting range. - static ConstantRange makeICmpRegion(unsigned Pred, - const ConstantRange &Other); + /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4) + static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &Other); + + /// Produce the largest range such that all values in the returned range + /// satisfy the given predicate with all values contained within Other. + /// Formally, this returns a subset of + /// 'intersection over all y in Other . { x : icmp op x y is true }'. If the + /// exact answer is not representable as a ConstantRange, the return value + /// will be a proper subset of the above. + /// + /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2) + static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &Other); /// Return the lower value for this range. /// @@ -208,8 +221,8 @@ public: ConstantRange sub(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting - /// from a multiplication of a value in this range and a value in \p Other. - /// TODO: This isn't fully implemented yet. + /// from a multiplication of a value in this range and a value in \p Other, + /// treating both this and \p Other as unsigned ranges. ConstantRange multiply(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 9479ba4..3e1f974 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -108,7 +108,14 @@ private: unsigned StackNaturalAlign; - enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips }; + enum ManglingModeT { + MM_None, + MM_ELF, + MM_MachO, + MM_WinCOFF, + MM_WinCOFFX86, + MM_Mips + }; ManglingModeT ManglingMode; SmallVector<unsigned char, 8> LegalIntWidths; @@ -116,6 +123,9 @@ private: /// \brief Primitive type alignment data. SmallVector<LayoutAlignElem, 16> Alignments; + /// \brief The string representation used to create this DataLayout + std::string StringRepresentation; + typedef SmallVector<PointerAlignElem, 8> PointersTy; PointersTy Pointers; @@ -185,6 +195,7 @@ public: DataLayout &operator=(const DataLayout &DL) { clear(); + StringRepresentation = DL.StringRepresentation; BigEndian = DL.isBigEndian(); StackNaturalAlign = DL.StackNaturalAlign; ManglingMode = DL.ManglingMode; @@ -209,8 +220,12 @@ public: /// \brief Returns the string representation of the DataLayout. /// /// This representation is in the same format accepted by the string - /// constructor above. - std::string getStringRepresentation() const; + /// constructor above. This should not be used to compare two DataLayout as + /// different string can represent the same layout. + std::string getStringRepresentation() const { return StringRepresentation; } + + /// \brief Test if the DataLayout was constructed from an empty string. + bool isDefault() const { return StringRepresentation.empty(); } /// \brief Returns true if the specified type is known to be a native integer /// type supported by the CPU. @@ -236,7 +251,7 @@ public: unsigned getStackAlignment() const { return StackNaturalAlign; } bool hasMicrosoftFastStdCallMangling() const { - return ManglingMode == MM_WINCOFF; + return ManglingMode == MM_WinCOFFX86; } bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } @@ -244,7 +259,7 @@ public: const char *getLinkerPrivateGlobalPrefix() const { if (ManglingMode == MM_MachO) return "l"; - return getPrivateGlobalPrefix(); + return ""; } char getGlobalPrefix() const { @@ -252,9 +267,10 @@ public: case MM_None: case MM_ELF: case MM_Mips: + case MM_WinCOFF: return '\0'; case MM_MachO: - case MM_WINCOFF: + case MM_WinCOFFX86: return '_'; } llvm_unreachable("invalid mangling mode"); @@ -269,7 +285,8 @@ public: case MM_Mips: return "$"; case MM_MachO: - case MM_WINCOFF: + case MM_WinCOFF: + case MM_WinCOFFX86: return "L"; } llvm_unreachable("invalid mangling mode"); @@ -451,22 +468,6 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) { return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P)); } -class DataLayoutPass : public ImmutablePass { - DataLayout DL; - -public: - /// This has to exist, because this is a pass, but it should never be used. - DataLayoutPass(); - ~DataLayoutPass(); - - const DataLayout &getDataLayout() const { return DL; } - - static char ID; // Pass identification, replacement for typeid - - bool doFinalization(Module &M) override; - bool doInitialization(Module &M) override; -}; - /// Used to lazily calculate structure layout information for a target machine, /// based on the DataLayout structure. class StructLayout { diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index d2e5975..0163c05 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -165,7 +165,6 @@ protected: GlobalVariable *getGlobalVariableField(unsigned Elt) const; Constant *getConstantField(unsigned Elt) const; Function *getFunctionField(unsigned Elt) const; - void replaceFunctionField(unsigned Elt, Function *F); public: explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} @@ -175,6 +174,10 @@ public: 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. @@ -215,29 +218,49 @@ public: return getHeaderIterator(Index).getNumber<T>(); } - uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); } - - bool isDerivedType() const; - bool isCompositeType() const; - bool isSubroutineType() const; - bool isBasicType() const; - bool isVariable() const; - bool isSubprogram() const; - bool isGlobalVariable() const; - bool isScope() const; - bool isFile() const; - bool isCompileUnit() const; - bool isNameSpace() const; - bool isLexicalBlockFile() const; - bool isLexicalBlock() const; - bool isSubrange() const; - bool isEnumerator() const; - bool isType() const; - bool isTemplateTypeParameter() const; - bool isTemplateValueParameter() const; - bool isObjCProperty() const; - bool isImportedEntity() const; - bool isExpression() const; + uint16_t getTag() const { + if (auto *N = dyn_cast_or_null<DebugNode>(get())) + return N->getTag(); + return 0; + } + + 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; @@ -247,29 +270,43 @@ public: void replaceAllUsesWith(MDNode *D); }; -#define RETURN_FROM_RAW(VALID, DEFAULT) \ +#define RETURN_FROM_RAW(VALID, UNUSED) \ do { \ - if (auto *N = getRaw()) \ - return VALID; \ - return DEFAULT; \ + auto *N = get(); \ + assert(N && "Expected non-null in accessor"); \ + return VALID; \ } while (false) #define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ do { \ - if (auto *N = getRaw()) \ - return DESC(dyn_cast_or_null<MDNode>(VALID)); \ - return DESC(static_cast<const MDNode *>(nullptr)); \ + 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 { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - 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 getHeaderFieldAs<int64_t>(1); } - int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); } + int64_t getLo() const { RETURN_FROM_RAW(N->getLo(), 0); } + int64_t getCount() const { RETURN_FROM_RAW(N->getCount(), 0); } bool Verify() const; }; @@ -290,14 +327,22 @@ typedef DITypedArray<DIDescriptor> DIArray; /// 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 { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIEnumerator(const MDEnumerator *N) : DIDescriptor(N) {} - StringRef getName() const { return getHeaderField(1); } - int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); } + 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(); + } + + StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } + int64_t getEnumValue() const { RETURN_FROM_RAW(N->getValue(), 0); } bool Verify() const; }; @@ -316,12 +361,17 @@ typedef DITypedArray<DITypeRef> DITypeArray; /// DIScopes that are scopes in the strict lexical scope sense /// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. class DIScope : public DIDescriptor { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - 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. /// @@ -362,6 +412,8 @@ 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); } }; template <typename T> @@ -413,12 +465,18 @@ template <> DIRef<DIType>::DIRef(const Metadata *V); /// 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 { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - 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"); @@ -427,15 +485,17 @@ public: bool Verify() const; - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - uint64_t getSizeInBits() const { return getHeaderFieldAs<unsigned>(3); } - uint64_t getAlignInBits() const { return getHeaderFieldAs<unsigned>(4); } + 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 getHeaderFieldAs<unsigned>(5); } - unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); } + 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; } @@ -473,8 +533,19 @@ public: class DIBasicType : public DIType { public: explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} + DIBasicType(const MDBasicType *N) : DIType(N) {} - unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); } + 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; }; @@ -484,25 +555,45 @@ public: /// 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 { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} + DIDerivedType(const MDDerivedTypeBase *N) : DIType(N) {} - DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); } + 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; + MDNode *getObjCProperty() const { + if (auto *N = dyn_cast<MDDerivedType>(get())) + return dyn_cast_or_null<MDNode>(N->getExtraData()); + return nullptr; + } DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DITypeRef>(4); + 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()); - return getConstantField(4); + 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; @@ -519,18 +610,27 @@ public: // base type in a single DIType field. class DICompositeType : public DIDerivedType { friend class DIBuilder; - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; /// \brief Set the array of member DITypes. void setArraysHelper(MDNode *Elements, MDNode *TParams); public: explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} + DICompositeType(const MDCompositeTypeBase *N) : DIDerivedType(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 getFieldAs<DIArray>(4); + RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getElements()); } private: @@ -544,16 +644,22 @@ private: } public: - unsigned getRunTimeLang() const { return getHeaderFieldAs<unsigned>(7); } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); } + unsigned getRunTimeLang() const { RETURN_FROM_RAW(N->getRuntimeLang(), 0); } + DITypeRef getContainingType() const { + RETURN_REF_FROM_RAW(DITypeRef, N->getVTableHolder()); + } private: /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); public: - DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } - MDString *getIdentifier() const; + DIArray getTemplateParams() const { + RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getTemplateParams()); + } + MDString *getIdentifier() const { + RETURN_FROM_RAW(N->getRawIdentifier(), nullptr); + } bool Verify() const; }; @@ -561,100 +667,163 @@ public: class DISubroutineType : public DICompositeType { public: explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} + DISubroutineType(const MDSubroutineType *N) : DICompositeType(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 getFieldAs<DITypedArray<DITypeRef>>(4); + RETURN_DESCRIPTOR_FROM_RAW(DITypedArray<DITypeRef>, N->getTypeArray()); } }; /// \brief This is a wrapper for a file. class DIFile : public DIScope { - friend class DIDescriptor; - 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(); + } /// \brief Retrieve the MDNode for the directory/file pair. - MDNode *getFileNode() const; + MDNode *getFileNode() const { return get(); } bool Verify() const; }; /// \brief A wrapper for a compile unit. class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} + DICompileUnit(const MDCompileUnit *N) : DIScope(N) {} - dwarf::SourceLanguage getLanguage() const { - return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1)); + 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(); } - StringRef getProducer() const { return getHeaderField(2); } - bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; } - StringRef getFlags() const { return getHeaderField(4); } - unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); } + 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); + } - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedEntities() const; + 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 getHeaderField(6); } - unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); } + 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 { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} + DISubprogram(const MDSubprogram *N) : DIScope(N) {} - StringRef getName() const { return getHeaderField(1); } - StringRef getDisplayName() const { return getHeaderField(2); } - StringRef getLinkageName() const { return getHeaderField(3); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } + 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 getHeaderFieldAs<unsigned>(5); } - unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); } + unsigned isLocalToUnit() const { RETURN_FROM_RAW(N->isLocalToUnit(), 0); } + unsigned isDefinition() const { RETURN_FROM_RAW(N->isDefinition(), 0); } - unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); } - unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); } + unsigned getVirtuality() const { RETURN_FROM_RAW(N->getVirtuality(), 0); } + unsigned getVirtualIndex() const { RETURN_FROM_RAW(N->getVirtualIndex(), 0); } - unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); } + unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } - unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); } + 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 getHeaderFieldAs<unsigned>(11); } + unsigned getScopeLineNumber() const { RETURN_FROM_RAW(N->getScopeLine(), 0); } - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); } + DIScopeRef getContext() const { + RETURN_REF_FROM_RAW(DIScopeRef, N->getScope()); + } + DISubroutineType getType() const { + RETURN_DESCRIPTOR_FROM_RAW(DISubroutineType, N->getType()); + } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); } + 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 { return getFunctionField(5); } - void replaceFunction(Function *F) { replaceFunctionField(5, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } + 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 getFieldAs<DISubprogram>(7); + RETURN_DESCRIPTOR_FROM_RAW(DISubprogram, N->getDeclaration()); + } + MDNode *getVariablesNodes() const { return getVariables(); } + DIArray getVariables() const { + RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getVariables()); } - MDNode *getVariablesNodes() const; - DIArray getVariables() const; unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } /// \brief Check for the "private" access specifier. @@ -695,9 +864,31 @@ public: class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(2); } + DILexicalBlock(const MDLexicalBlock *N) : DIScope(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; }; @@ -705,6 +896,18 @@ public: 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?!? @@ -714,21 +917,36 @@ public: } unsigned getLineNumber() const { return getScope().getLineNumber(); } unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } - unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); } + DILexicalBlock getScope() const { + RETURN_DESCRIPTOR_FROM_RAW(DILexicalBlock, N->getScope()); + } + unsigned getDiscriminator() const { + RETURN_FROM_RAW(N->getDiscriminator(), 0); + } bool Verify() const; }; /// \brief A wrapper for a C++ style name space. class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - DIScope getContext() const { return getFieldAs<DIScope>(2); } + 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; }; @@ -737,10 +955,21 @@ class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) : DIDescriptor(N) {} + DITemplateTypeParameter(const MDTemplateTypeParameter *N) : DIDescriptor(N) {} - StringRef getName() const { return getHeaderField(1); } + 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 getFieldAs<DITypeRef>(2); } + DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } bool Verify() const; }; @@ -749,40 +978,67 @@ class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) : DIDescriptor(N) {} + DITemplateValueParameter(const MDTemplateValueParameter *N) + : DIDescriptor(N) {} - StringRef getName() const { return getHeaderField(1); } + 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(); + } - DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - Metadata *getValue() const; + 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; }; /// \brief This is a wrapper for a global variable. class DIGlobalVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; + DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } public: explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIGlobalVariable(const MDGlobalVariable *N) : DIDescriptor(N) {} - StringRef getName() const { return getHeaderField(1); } - StringRef getDisplayName() const { return getHeaderField(2); } - StringRef getLinkageName() const { return getHeaderField(3); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); } - unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); } + 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 getFieldAs<DIScope>(1); } - StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(2).getDirectory(); + DIScope getContext() const { + RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } + 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 { return getGlobalVariableField(4); } - Constant *getConstant() const { return getConstantField(4); } + 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 getFieldAs<DIDerivedType>(5); + RETURN_DESCRIPTOR_FROM_RAW(DIDerivedType, + N->getStaticDataMemberDeclaration()); } bool Verify() const; @@ -790,34 +1046,45 @@ public: /// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). class DIVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; + unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } public: explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIVariable(const MDLocalVariable *N) : DIDescriptor(N) {} - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - // FIXME: Line number and arg number shouldn't be merged together like this. - return (getHeaderFieldAs<unsigned>(2) << 8) >> 8; + 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(); } - unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; } - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIFile getFile() const { return getFieldAs<DIFile>(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } + 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 (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0; + return (getFlags() & FlagArtificial) != 0; } bool isObjectPointer() const { - return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0; + return (getFlags() & FlagObjectPointer) != 0; } /// \brief If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; + MDNode *getInlinedAt() const { + RETURN_DESCRIPTOR_FROM_RAW(DIDescriptor, N->getInlinedAt()); + } bool Verify() const; @@ -843,25 +1110,28 @@ public: /// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const /// and have DW_OP_plus consume the topmost elements on the stack. class DIExpression : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} + DIExpression(const MDExpression *N) : DIDescriptor(N) {} - bool Verify() const; + 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 { - if (!DbgNode) - return 0; - unsigned N = getNumHeaderFields(); - assert(N > 0 && "missing tag"); - return N - 1; - } + unsigned getNumElements() const { return get()->getNumElements(); } /// \brief return the Idx'th complex address element. - uint64_t getElement(unsigned Idx) const; + uint64_t getElement(unsigned I) const { return get()->getElement(I); } /// \brief Return whether this is a piece of an aggregate variable. bool isBitPiece() const; @@ -874,34 +1144,33 @@ public: /// \brief A lightweight wrapper around an element of a DIExpression. class Operand { friend class iterator; - DIHeaderFieldIterator I; + MDExpression::element_iterator I; Operand() {} - Operand(DIHeaderFieldIterator I) : I(I) {} + 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 { - DIHeaderFieldIterator In = I; + MDExpression::element_iterator In = I; std::advance(In, N); - return In.getNumber<uint64_t>(); + return *In; } - operator uint64_t () const { return I.getNumber<uint64_t>(); } - /// \brief Returns underlying DIHeaderFieldIterator. - const DIHeaderFieldIterator &getBase() const { return I; } + 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. - Operand getNext() const; + 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; - DIHeaderFieldIterator I; + MDExpression::element_iterator I; Operand Tmp; - iterator(DIHeaderFieldIterator I) : I(I) {} + public: - iterator() {} - iterator(const DIExpression &Expr) : I(++Expr.header_begin()) {} + iterator(MDExpression::element_iterator I) : I(I) {} const Operand &operator*() { return Tmp = Operand(I); } const Operand *operator->() { return &(Tmp = Operand(I)); } iterator &operator++() { @@ -928,19 +1197,27 @@ public: } }; - iterator begin() const; - iterator end() const; + iterator begin() const { return get()->elements_begin(); } + iterator end() const { return get()->elements_end(); } }; /// \brief This object holds location information. /// /// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { - MDLocation *getRaw() const { return dyn_cast_or_null<MDLocation>(get()); } - 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 { @@ -983,19 +1260,31 @@ public: }; class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} + DIObjCProperty(const MDObjCProperty *N) : DIDescriptor(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(); + } - StringRef getObjCPropertyName() const { return getHeaderField(1); } - DIFile getFile() const { return getFieldAs<DIFile>(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } + 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); } - StringRef getObjCPropertyGetterName() const { return getHeaderField(3); } - StringRef getObjCPropertySetterName() const { return getHeaderField(4); } - unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); } + 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; } @@ -1019,28 +1308,42 @@ public: /// /// \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 getFieldAs<DIType>(2); } + DIType getType() const { RETURN_DESCRIPTOR_FROM_RAW(DIType, N->getType()); } bool Verify() const; }; /// \brief An imported module (C++ using directive or similar). class DIImportedEntity : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: DIImportedEntity() = default; explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIDescriptorRef getEntity() const { return getFieldAs<DIDescriptorRef>(2); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } - StringRef getName() const { return getHeaderField(2); } + DIImportedEntity(const MDImportedEntity *N) : DIDescriptor(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(); + } + + 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; }; #undef RETURN_FROM_RAW #undef RETURN_DESCRIPTOR_FROM_RAW +#undef RETURN_REF_FROM_RAW /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1098,9 +1401,6 @@ public: /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); - /// \brief Process DIExpression. - void processExpression(DIExpression Expr); - /// \brief Clear all lists. void reset(); diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 4534a14..d7563fc 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -41,53 +41,6 @@ namespace llvm { -/// \brief Debug location. -/// -/// A debug location in source code, used for debug info and otherwise. -class MDLocation : public MDNode { - friend class LLVMContextImpl; - friend class MDNode; - - MDLocation(LLVMContext &C, StorageType Storage, unsigned Line, - unsigned Column, ArrayRef<Metadata *> MDs); - ~MDLocation() { dropAllReferences(); } - - static MDLocation *getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, StorageType Storage, - bool ShouldCreate = true); - - TempMDLocation cloneImpl() const { - return getTemporary(getContext(), getLine(), getColumn(), getScope(), - getInlinedAt()); - } - - // Disallow replacing operands. - void replaceOperandWith(unsigned I, Metadata *New) = delete; - -public: - DEFINE_MDNODE_GET(MDLocation, - (unsigned Line, unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr), - (Line, Column, Scope, InlinedAt)) - - /// \brief Return a (temporary) clone of this. - TempMDLocation clone() const { return cloneImpl(); } - - unsigned getLine() const { return SubclassData32; } - unsigned getColumn() const { return SubclassData16; } - Metadata *getScope() const { return getOperand(0); } - Metadata *getInlinedAt() const { - if (getNumOperands() == 2) - return getOperand(1); - return nullptr; - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLocationKind; - } -}; - /// \brief Tagged DWARF-like metadata node. /// /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, @@ -146,7 +99,6 @@ public: case MDTemplateValueParameterKind: case MDGlobalVariableKind: case MDLocalVariableKind: - case MDExpressionKind: case MDObjCPropertyKind: case MDImportedEntityKind: return true; @@ -330,7 +282,16 @@ protected: ~MDScope() {} public: - Metadata *getFile() const { return getOperand(0); } + /// \brief Return the 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 { + return isa<MDFile>(this) ? const_cast<MDScope *>(this) + : static_cast<Metadata *>(getOperand(0)); + } static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { @@ -351,6 +312,52 @@ public: } }; +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class MDFile : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) + : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~MDFile() {} + + static MDFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static MDFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempMDFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempMDFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs<MDString>(0); } + MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDFileKind; + } +}; + /// \brief Base class for types. /// /// TODO: Remove the hardcoded name and context, since many types don't use @@ -373,6 +380,10 @@ protected: ~MDType() {} public: + TempMDType clone() const { + return TempMDType(cast<MDType>(MDNode::clone().release())); + } + unsigned getLine() const { return Line; } uint64_t getSizeInBits() const { return SizeInBits; } uint64_t getAlignInBits() const { return AlignInBits; } @@ -384,6 +395,11 @@ public: MDString *getRawName() const { return getOperandAs<MDString>(2); } + void setFlags(unsigned NewFlags) { + assert(!isUniqued() && "Cannot set flags on uniqued nodes"); + Flags = NewFlags; + } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -433,6 +449,8 @@ class MDBasicType : public MDType { } public: + DEFINE_MDNODE_GET(MDBasicType, (unsigned Tag, StringRef Name), + (Tag, Name, 0, 0, 0)) DEFINE_MDNODE_GET(MDBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding), @@ -719,52 +737,6 @@ public: } }; -/// \brief File. -/// -/// TODO: Merge with directory/file node (including users). -/// TODO: Canonicalize paths on creation. -class MDFile : public MDScope { - friend class LLVMContextImpl; - friend class MDNode; - - MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) - : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} - ~MDFile() {} - - static MDFile *getImpl(LLVMContext &Context, StringRef Filename, - StringRef Directory, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, getCanonicalMDString(Context, Filename), - getCanonicalMDString(Context, Directory), Storage, - ShouldCreate); - } - static MDFile *getImpl(LLVMContext &Context, MDString *Filename, - MDString *Directory, StorageType Storage, - bool ShouldCreate = true); - - TempMDFile cloneImpl() const { - return getTemporary(getContext(), getFilename(), getDirectory()); - } - -public: - DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), - (Filename, Directory)) - DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), - (Filename, Directory)) - - TempMDFile clone() const { return cloneImpl(); } - - StringRef getFilename() const { return getStringOperand(0); } - StringRef getDirectory() const { return getStringOperand(1); } - - MDString *getRawFilename() const { return getOperandAs<MDString>(0); } - MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDFileKind; - } -}; - /// \brief Compile unit. class MDCompileUnit : public MDScope { friend class LLVMContextImpl; @@ -875,11 +847,96 @@ public: } }; +/// \brief A scope for locals. +/// +/// A legal scope for lexical blocks, local variables, and debug info +/// locations. Subclasses are \a MDSubprogram, \a MDLexicalBlock, and \a +/// MDLexicalBlockFile. +class MDLocalScope : public MDScope { +protected: + MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops) + : MDScope(C, ID, Storage, Tag, Ops) {} + ~MDLocalScope() {} + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubprogramKind || + MD->getMetadataID() == MDLexicalBlockKind || + MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class MDLocation : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + MDLocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef<Metadata *> MDs); + ~MDLocation() { dropAllReferences(); } + + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, MDLocalScope *Scope, + MDLocation *InlinedAt, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(InlinedAt), Storage, ShouldCreate); + } + + TempMDLocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) = delete; + +public: + DEFINE_MDNODE_GET(MDLocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + DEFINE_MDNODE_GET(MDLocation, + (unsigned Line, unsigned Column, MDLocalScope *Scope, + MDLocation *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + + /// \brief Return a (temporary) clone of this. + TempMDLocation clone() const { return cloneImpl(); } + + unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return SubclassData16; } + MDLocalScope *getScope() const { + return cast_or_null<MDLocalScope>(getRawScope()); + } + MDLocation *getInlinedAt() const { + return cast_or_null<MDLocation>(getRawInlinedAt()); + } + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocationKind; + } +}; + /// \brief Subprogram description. /// /// TODO: Remove DisplayName. It's always equal to Name. /// TODO: Split up flags. -class MDSubprogram : public MDScope { +class MDSubprogram : public MDLocalScope { friend class LLVMContextImpl; friend class MDNode; @@ -896,7 +953,8 @@ class MDSubprogram : public MDScope { unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, unsigned Flags, bool IsLocalToUnit, bool IsDefinition, bool IsOptimized, ArrayRef<Metadata *> Ops) - : MDScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), + : MDLocalScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, + Ops), Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} @@ -1004,11 +1062,11 @@ public: } }; -class MDLexicalBlockBase : public MDScope { +class MDLexicalBlockBase : public MDLocalScope { protected: MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef<Metadata *> Ops) - : MDScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + : MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} ~MDLexicalBlockBase() {} public: @@ -1407,6 +1465,18 @@ public: unsigned getFlags() const { return Flags; } Metadata *getInlinedAt() const { return getOperand(4); } + /// \brief Get an inlined version of 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)); + } + MDLocalVariable *withoutInline() const { return withInline(nullptr); } + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind; } @@ -1415,17 +1485,16 @@ public: /// \brief DWARF expression. /// /// TODO: Co-allocate the expression elements. -/// TODO: Drop fake DW_TAG_expression and separate from DebugNode. /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary /// storage types. -class MDExpression : public DebugNode { +class MDExpression : public MDNode { friend class LLVMContextImpl; friend class MDNode; std::vector<uint64_t> Elements; MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) - : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None), + : MDNode(C, MDExpressionKind, Storage, None), Elements(Elements.begin(), Elements.end()) {} ~MDExpression() {} diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 86e6441..c29d5bf 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -103,7 +103,6 @@ namespace llvm { void dump(const LLVMContext &) const { dump(); } /// \brief prints source location /path/to/file.exe:line:col @[inlined at] void print(raw_ostream &OS) const; - void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; } // end namespace llvm diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index c6a8854..6db5a40 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -20,6 +20,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" +#include <functional> namespace llvm { diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 6f57dc2..ae2f2e1 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -53,6 +53,8 @@ public: /// virtual std::error_code MaterializeModule(Module *M) = 0; + virtual std::error_code materializeMetadata() = 0; + virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0; }; diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index aaecc1d..002e5e7 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -346,8 +346,6 @@ public: inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } - const DataLayout *getDataLayout() const; - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 33649d7..617e2bc 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -351,8 +351,8 @@ public: } /// \brief Fetch the type representing a pointer to an integer value. - IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) { - return DL->getIntPtrType(Context, AddrSpace); + IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) { + return DL.getIntPtrType(Context, AddrSpace); } //===--------------------------------------------------------------------===// @@ -1017,6 +1017,10 @@ public: } Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateGEP(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; @@ -1026,7 +1030,7 @@ public: if (i == e) return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); } - return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { @@ -1039,19 +1043,19 @@ public: if (i == e) return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); } - return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, IdxList), Name); } Value *CreateGEP(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(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } Value *CreateInBoundsGEP(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(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); @@ -1059,7 +1063,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { @@ -1068,7 +1072,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { @@ -1080,7 +1084,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { @@ -1092,7 +1096,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); @@ -1100,7 +1104,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { @@ -1109,7 +1113,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -1121,7 +1125,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -1133,7 +1137,7 @@ public: if (Constant *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, 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); @@ -1486,6 +1490,16 @@ public: return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } + Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> IntMask, + const Twine &Name = "") { + size_t MaskSize = IntMask.size(); + SmallVector<Constant*, 8> MaskVec(MaskSize); + for (size_t i = 0; i != MaskSize; ++i) + MaskVec[i] = getInt32(IntMask[i]); + Value *Mask = ConstantVector::get(MaskVec); + return CreateShuffleVector(V1, V2, Mask, Name); + } + Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs, const Twine &Name = "") { @@ -1595,7 +1609,7 @@ public: "trying to create an alignment assumption on a non-pointer?"); PointerType *PtrTy = cast<PointerType>(PtrValue->getType()); - Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); Value *Mask = ConstantInt::get(IntPtrTy, diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 84ae9df..6ae4122 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -189,6 +189,20 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. + // + // The encoding of the flag word is currently: + // Bits 2-0 - A Kind_* value indicating the kind of the operand. + // Bits 15-3 - The number of SDNode operands associated with this inline + // assembly operand. + // If bit 31 is set: + // Bit 30-16 - The operand number that this operand must match. + // When bits 2-0 are Kind_Mem, the Constraint_* value must be + // obtained from the flags for this operand number. + // Else if bits 2-0 are Kind_Mem: + // Bit 30-16 - A Constraint_* value indicating the original constraint + // code. + // Else: + // Bit 30-16 - The register class ID to use for the operand. enum : uint32_t { // Fixed operands on an INLINEASM SDNode. @@ -220,6 +234,26 @@ public: Kind_Imm = 5, // Immediate. Kind_Mem = 6, // Memory operand, "m". + // Memory constraint codes. + // These could be tablegenerated but there's little need to do that since + // there's plenty of space in the encoding to support the union of all + // constraint codes for all targets. + Constraint_Unknown = 0, + Constraint_es, + Constraint_i, + Constraint_m, + Constraint_o, + Constraint_v, + Constraint_Q, + Constraint_R, + Constraint_S, + Constraint_T, + Constraint_Z, + Constraint_ZC, + Constraint_Zy, + Constraints_Max = Constraint_Zy, + Constraints_ShiftAmount = 16, + Flag_MatchingOperand = 0x80000000 }; @@ -252,6 +286,20 @@ public: return InputFlag | (RC << 16); } + /// Augment an existing flag word returned by getFlagWord with the constraint + /// code for a memory constraint. + static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { + assert(Constraint <= 0x7fff && "Too large a memory constraint ID"); + assert(Constraint <= Constraints_Max && "Unknown constraint ID"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); + return InputFlag | (Constraint << Constraints_ShiftAmount); + } + + static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { + assert(isMemKind(InputFlag)); + return InputFlag & ~(0x7fff << Constraints_ShiftAmount); + } + static unsigned getKind(unsigned Flags) { return Flags & 7; } @@ -266,6 +314,11 @@ public: return getKind(Flag) == Kind_Clobber; } + static unsigned getMemoryConstraintID(unsigned Flag) { + assert(isMemKind(Flag)); + return (Flag >> Constraints_ShiftAmount) & 0x7fff; + } + /// getNumOperandRegisters - Extract the number of registers field from the /// inline asm operand flag. static unsigned getNumOperandRegisters(unsigned Flag) { diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 0bb2854..f3ce649 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -27,15 +27,14 @@ namespace llvm { // This class implements inst_begin() & inst_end() for // inst_iterator and const_inst_iterator's. // -template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t> -class InstIterator { - typedef _BB_t BBty; - typedef _BB_i_t BBIty; - typedef _BI_t BIty; - typedef _II_t IIty; - _BB_t *BBs; // BasicBlocksType - _BB_i_t BB; // BasicBlocksType::iterator - _BI_t BI; // BasicBlock::iterator +template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator { + typedef BB_t BBty; + typedef BB_i_t BBIty; + typedef BI_t BIty; + typedef II_t IIty; + BB_t *BBs; // BasicBlocksType + BB_i_t BB; // BasicBlocksType::iterator + BI_t BI; // BasicBlock::iterator public: typedef std::bidirectional_iterator_tag iterator_category; typedef IIty value_type; diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index e086282..3a33f43 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -570,10 +570,9 @@ public: /// This ensures that any pointer<->integer cast has enough bits in the /// integer and any other cast is a bitcast. static bool isBitOrNoopPointerCastable( - Type *SrcTy, ///< The Type from which the value should be cast. - Type *DestTy, ///< The Type to which the value should be cast. - const DataLayout *Layout = 0 ///< Optional DataLayout. - ); + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout &DL); /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. @@ -621,9 +620,9 @@ public: ) const; /// @brief Determine if this cast is a no-op cast. - bool isNoopCast( - const DataLayout *DL ///< DataLayout to get the Int Ptr type from. - ) const; + /// + /// \param DL is the DataLayout to get the Int Ptr type from. + bool isNoopCast(const DataLayout &DL) const; /// Determine how a pair of casts can be eliminated, if they can be at all. /// This is a helper function for both CastInst and ConstantExpr. diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index dfece3e..dc96b57 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -54,7 +54,12 @@ public: inline const BasicBlock *getParent() const { return Parent; } inline BasicBlock *getParent() { return Parent; } - const DataLayout *getDataLayout() const; + /// \brief Return the module owning the function this instruction belongs to + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the instruction does not have a + /// parent, or the parent basic block does not have a parent function. + const Module *getModule() const; /// removeFromParent - This method unlinks 'this' from the containing basic /// block, but does not delete it. diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 83f9d04..52fa360 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -794,28 +794,31 @@ class GetElementPtrInst : public Instruction { /// list of indices. The first ctor can optionally insert before an existing /// instruction, the second appends the new instruction to the specified /// BasicBlock. - inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore); - inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd); + inline GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + inline GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); + protected: GetElementPtrInst *clone_impl() const override; public: - static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { unsigned Values = 1 + unsigned(IdxList.size()); - return new(Values) - GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertBefore); } - static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values = 1 + unsigned(IdxList.size()); - return new(Values) - GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertAtEnd); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertAtEnd); } /// Create an "inbounds" getelementptr. See the documentation for the @@ -824,7 +827,14 @@ public: ArrayRef<Value *> IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr){ - GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore); + return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertBefore); + } + static GetElementPtrInst * + CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + GetElementPtrInst *GEP = + Create(PointeeType, Ptr, IdxList, NameStr, InsertBefore); GEP->setIsInBounds(true); return GEP; } @@ -832,7 +842,14 @@ public: ArrayRef<Value *> IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { - GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertAtEnd); + return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertAtEnd); + } + static GetElementPtrInst *CreateInBounds(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = + Create(PointeeType, Ptr, IdxList, NameStr, InsertAtEnd); GEP->setIsInBounds(true); return GEP; } @@ -846,12 +863,12 @@ public: } Type *getSourceElementType() const { - SequentialType *Ty = cast<SequentialType>(getPointerOperandType()); - if (VectorType *VTy = dyn_cast<VectorType>(Ty)) - Ty = cast<SequentialType>(VTy->getElementType()); - return Ty->getElementType(); + return cast<SequentialType>(getPointerOperandType()->getScalarType()) + ->getElementType(); } + Type *getResultElementType() const { return getType()->getElementType(); } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space @@ -960,27 +977,25 @@ struct OperandTraits<GetElementPtrInst> : public VariadicOperandTraits<GetElementPtrInst, 1> { }; -GetElementPtrInst::GetElementPtrInst(Value *Ptr, - ArrayRef<Value *> IdxList, - unsigned Values, +GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(getGEPReturnType(Ptr, IdxList), - GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - Values, - Values, InsertBefore) { + : Instruction(getGEPReturnType(Ptr, IdxList), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertBefore) { init(Ptr, IdxList, NameStr); + assert(!PointeeType || PointeeType == getSourceElementType()); } -GetElementPtrInst::GetElementPtrInst(Value *Ptr, - ArrayRef<Value *> IdxList, - unsigned Values, +GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(getGEPReturnType(Ptr, IdxList), - GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - Values, - Values, InsertAtEnd) { + : Instruction(getGEPReturnType(Ptr, IdxList), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertAtEnd) { init(Ptr, IdxList, NameStr); + assert(!PointeeType || PointeeType == getSourceElementType()); } @@ -1201,11 +1216,15 @@ public: /// @returns true if the predicate of this instruction is EQ or NE. /// \brief Determine if this is an equality predicate. - bool isEquality() const { - return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE || - getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE; + static bool isEquality(Predicate Pred) { + return Pred == FCMP_OEQ || Pred == FCMP_ONE || Pred == FCMP_UEQ || + Pred == FCMP_UNE; } + /// @returns true if the predicate of this instruction is EQ or NE. + /// \brief Determine if this is an equality predicate. + bool isEquality() const { return isEquality(getPredicate()); } + /// @returns true if the predicate of this instruction is commutative. /// \brief Determine if this is a commutative predicate. bool isCommutative() const { @@ -1908,6 +1927,9 @@ public: typedef const unsigned* idx_iterator; inline idx_iterator idx_begin() const { return Indices.begin(); } inline idx_iterator idx_end() const { return Indices.end(); } + inline iterator_range<idx_iterator> indices() const { + return iterator_range<idx_iterator>(idx_begin(), idx_end()); + } Value *getAggregateOperand() { return getOperand(0); @@ -2019,6 +2041,9 @@ public: typedef const unsigned* idx_iterator; inline idx_iterator idx_begin() const { return Indices.begin(); } inline idx_iterator idx_end() const { return Indices.end(); } + inline iterator_range<idx_iterator> indices() const { + return iterator_range<idx_iterator>(idx_begin(), idx_end()); + } Value *getAggregateOperand() { return getOperand(0); diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index d434432..bf0adc3 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -82,13 +82,18 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(1))->getMetadata()); + MDLocalVariable *getVariable() const { + return cast<MDLocalVariable>(getRawVariable()); } - MDNode *getExpression() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + MDExpression *getExpression() const { + return cast<MDExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); + } + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -110,13 +115,18 @@ namespace llvm { return cast<ConstantInt>( const_cast<Value*>(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + MDLocalVariable *getVariable() const { + return cast<MDLocalVariable>(getRawVariable()); + } + MDExpression *getExpression() const { + return cast<MDExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } - MDNode *getExpression() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(3))->getMetadata()); + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(3))->getMetadata(); } // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index e89e65d..da9d8cb 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -261,10 +261,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_frameescape : Intrinsic<[], [llvm_vararg_ty]>; def int_framerecover : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty], - [IntrNoMem]>; + [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], @@ -412,10 +412,19 @@ def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; // eh.begincatch takes a pointer returned by a landingpad instruction and -// returns the exception object pointer for the exception to be handled. -def int_eh_begincatch : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; +// copies the exception object into the memory pointed to by the second +// parameter. If the second parameter is null, no copy occurs. +def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], + [NoCapture<0>, NoCapture<1>]>; 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. diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index b566956..78ee651 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -422,12 +422,42 @@ class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +class Hexagon_mem_memmemsi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; +class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + // // Hexagon_sf_df_Intrinsic<string GCCIntSuffix> // @@ -606,20 +636,126 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix> [IntrNoMem, Throws]>; -// This one below will not be generated from iset.py. -// So make sure, you don't overwrite this one. +// This one below will not be auto-generated, +// so make sure, you don't overwrite this one. // // BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1) // def int_hexagon_SI_to_SXTHI_asrh : Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">; // +// BUILTIN_INFO_NONCONST(brev_ldd,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldd : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldd">; +// +// BUILTIN_INFO_NONCONST(brev_ldw,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldw : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldw">; +// +// BUILTIN_INFO_NONCONST(brev_ldh,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldh : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldh">; +// +// BUILTIN_INFO_NONCONST(brev_lduh,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_lduh : +Hexagon_mem_memmemsi_Intrinsic<"brev_lduh">; +// +// BUILTIN_INFO_NONCONST(brev_ldb,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldb : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldb">; +// +// BUILTIN_INFO_NONCONST(brev_ldub,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldub : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldub">; +// // BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) // def int_hexagon_circ_ldd : Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; -// This one above will not be generated from iset.py. -// So make sure, you don't overwrite this one. +// +// BUILTIN_INFO_NONCONST(circ_ldw,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldw : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldw">; +// +// BUILTIN_INFO_NONCONST(circ_ldh,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldh : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldh">; +// +// BUILTIN_INFO_NONCONST(circ_lduh,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_lduh : +Hexagon_mem_memmemsisi_Intrinsic<"circ_lduh">; +// +// BUILTIN_INFO_NONCONST(circ_ldb,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldb : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldb">; +// +// BUILTIN_INFO_NONCONST(circ_ldub,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldub : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">; + +// +// BUILTIN_INFO_NONCONST(brev_stb,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_stb : +Hexagon_mem_memsisi_Intrinsic<"brev_stb">; +// +// BUILTIN_INFO_NONCONST(brev_sthhi,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_sthhi : +Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">; +// +// BUILTIN_INFO_NONCONST(brev_sth,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_sth : +Hexagon_mem_memsisi_Intrinsic<"brev_sth">; +// +// BUILTIN_INFO_NONCONST(brev_stw,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_stw : +Hexagon_mem_memsisi_Intrinsic<"brev_stw">; +// +// BUILTIN_INFO_NONCONST(brev_std,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_std : +Hexagon_mem_memdisi_Intrinsic<"brev_std">; +// +// BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4) +// +def int_hexagon_circ_std : +Hexagon_mem_memdisisi_Intrinsic<"circ_std">; +// +// BUILTIN_INFO_NONCONST(circ_stw,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_stw : +Hexagon_mem_memsisisi_Intrinsic<"circ_stw">; +// +// BUILTIN_INFO_NONCONST(circ_sth,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_sth : +Hexagon_mem_memsisisi_Intrinsic<"circ_sth">; +// +// BUILTIN_INFO_NONCONST(circ_sthhi,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_sthhi : +Hexagon_mem_memsisisi_Intrinsic<"circ_sthhi">; +// +// BUILTIN_INFO_NONCONST(circ_stb,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_stb : +Hexagon_mem_memsisisi_Intrinsic<"circ_stb">; + + // // BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) // diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 110d55d..95fc3e5 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -73,7 +73,7 @@ class PowerPC_Vec_FFF_Intrinsic<string GCCIntSuffix> [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16i8 /// vectors and returns one. These intrinsics have no side effects. class PowerPC_Vec_BBB_Intrinsic<string GCCIntSuffix> : PowerPC_Vec_Intrinsic<GCCIntSuffix, @@ -94,6 +94,12 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix> [llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +/// PowerPC_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2i64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_DDD_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Class Definitions. @@ -120,7 +126,6 @@ class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix> [llvm_double_ty], [llvm_double_ty, llvm_double_ty], [IntrNoMem]>; - //===----------------------------------------------------------------------===// // PowerPC Altivec Intrinsic Definitions. @@ -198,7 +203,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; - + + def int_ppc_altivec_vcmpequd : GCCBuiltin<"__builtin_altivec_vcmpequd">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsd : GCCBuiltin<"__builtin_altivec_vcmpgtsd">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtud : GCCBuiltin<"__builtin_altivec_vcmpgtud">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; @@ -242,7 +257,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], [IntrNoMem]>; - + + def int_ppc_altivec_vcmpequd_p : GCCBuiltin<"__builtin_altivec_vcmpequd_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsd_p : GCCBuiltin<"__builtin_altivec_vcmpgtsd_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtud_p : GCCBuiltin<"__builtin_altivec_vcmpgtud_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], [IntrNoMem]>; @@ -287,18 +312,22 @@ def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxsd : PowerPC_Vec_DDD_Intrinsic<"vmaxsd">; def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; +def int_ppc_altivec_vmaxud : PowerPC_Vec_DDD_Intrinsic<"vmaxud">; // Vector minimum. def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminsd : PowerPC_Vec_DDD_Intrinsic<"vminsd">; def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; +def int_ppc_altivec_vminud : PowerPC_Vec_DDD_Intrinsic<"vminud">; // Saturating adds. def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; @@ -361,12 +390,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulesw : GCCBuiltin<"__builtin_altivec_vmulesw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmuleuw : GCCBuiltin<"__builtin_altivec_vmuleuw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], @@ -374,12 +409,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulosw : GCCBuiltin<"__builtin_altivec_vmulosw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulouw : GCCBuiltin<"__builtin_altivec_vmulouw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; // Vector Sum Intructions. def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, @@ -489,6 +530,7 @@ def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; +def int_ppc_altivec_vrld : PowerPC_Vec_DDD_Intrinsic<"vrld">; let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // Miscellaneous. @@ -510,6 +552,41 @@ def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; +// Power8 Intrinsics +// Crypto +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + def int_ppc_altivec_crypto_vsbox : + GCCBuiltin<"__builtin_altivec_crypto_vsbox">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_ppc_altivec_crypto_vpermxor : + GCCBuiltin<"__builtin_altivec_crypto_vpermxor">, + 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 : + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_ppc_altivec_crypto_vshasigmaw : + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +} +def int_ppc_altivec_crypto_vcipher : + PowerPC_Vec_DDD_Intrinsic<"crypto_vcipher">; +def int_ppc_altivec_crypto_vcipherlast : + PowerPC_Vec_DDD_Intrinsic<"crypto_vcipherlast">; +def int_ppc_altivec_crypto_vncipher : + PowerPC_Vec_DDD_Intrinsic<"crypto_vncipher">; +def int_ppc_altivec_crypto_vncipherlast : + PowerPC_Vec_DDD_Intrinsic<"crypto_vncipherlast">; +def int_ppc_altivec_crypto_vpmsumb : + PowerPC_Vec_BBB_Intrinsic<"crypto_vpmsumb">; +def int_ppc_altivec_crypto_vpmsumh : + PowerPC_Vec_HHH_Intrinsic<"crypto_vpmsumh">; +def int_ppc_altivec_crypto_vpmsumw : + PowerPC_Vec_WWW_Intrinsic<"crypto_vpmsumw">; +def int_ppc_altivec_crypto_vpmsumd : + PowerPC_Vec_DDD_Intrinsic<"crypto_vpmsumd">; //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Definitions. @@ -719,3 +796,62 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>; } +//===----------------------------------------------------------------------===// +// PowerPC HTM Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + +def int_ppc_tbegin : + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_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 : + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortwci : + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortdc : + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortdci : + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">, + Intrinsic<[llvm_i32_ty], [], []>; +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 : + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_texasru : GCCBuiltin<"__builtin_get_texasru">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_tfhar : GCCBuiltin<"__builtin_get_tfhar">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_tfiar : GCCBuiltin<"__builtin_get_tfiar">, + Intrinsic<[llvm_i64_ty], [], []>; + +def int_ppc_set_texasr : GCCBuiltin<"__builtin_set_texasr">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_texasru : GCCBuiltin<"__builtin_set_texasru">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_tfhar : GCCBuiltin<"__builtin_set_tfhar">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_tfiar : GCCBuiltin<"__builtin_set_tfiar">, + Intrinsic<[], [llvm_i64_ty], []>; + +// Extended mnemonics +def int_ppc_tendall : GCCBuiltin<"__builtin_tendall">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tresume : GCCBuiltin<"__builtin_tresume">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">, + Intrinsic<[llvm_i32_ty], [], []>; + +def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">, + Intrinsic<[llvm_i64_ty], [], []>; +} diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 60deb32..39b8e3b 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -882,15 +882,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], [IntrNoMem]>; @@ -1156,12 +1147,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector blend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; @@ -1187,32 +1172,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; } -// Vector extract and insert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vextractf128_pd_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_pd256">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vextractf128_ps_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_ps256">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vextractf128_si_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_si256">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx_vinsertf128_pd_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_pd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vinsertf128_ps_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_ps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vinsertf128_si_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_si256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; -} - // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">, @@ -1734,15 +1693,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">, Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -1756,8 +1706,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_vbroadcast_ss_ps_256 : GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx2_vbroadcasti128 : - Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx2_pbroadcastb_128 : GCCBuiltin<"__builtin_ia32_pbroadcastb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; @@ -1811,13 +1759,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector extract and insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_vextracti128 : GCCBuiltin<"__builtin_ia32_extract128i256">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf32x4_512 : GCCBuiltin<"__builtin_ia32_extractf32x4_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty, diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 66589e0..0eb29bc 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -61,6 +61,7 @@ HANDLE_METADATA_LEAF(LocalAsMetadata) HANDLE_MDNODE_BRANCH(MDNode) HANDLE_MDNODE_LEAF(MDTuple) HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocation) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDExpression) HANDLE_SPECIALIZED_MDNODE_BRANCH(DebugNode) HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDebugNode) HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubrange) @@ -75,6 +76,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompositeType) HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubroutineType) HANDLE_SPECIALIZED_MDNODE_LEAF(MDFile) HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompileUnit) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLocalScope) HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubprogram) HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLexicalBlockBase) HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlock) @@ -86,7 +88,6 @@ HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateValueParameter) HANDLE_SPECIALIZED_MDNODE_BRANCH(MDVariable) HANDLE_SPECIALIZED_MDNODE_LEAF(MDGlobalVariable) HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocalVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDExpression) HANDLE_SPECIALIZED_MDNODE_LEAF(MDObjCProperty) HANDLE_SPECIALIZED_MDNODE_LEAF(MDImportedEntity) diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index ff8f837..a31bdbf 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -32,9 +32,8 @@ class Module; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; - enum LLVMConstants : uint32_t { - DEBUG_METADATA_VERSION = 2 // Current debug info version number. + DEBUG_METADATA_VERSION = 3 // Current debug info version number. }; /// \brief Root of the metadata hierarchy. @@ -104,15 +103,48 @@ public: unsigned getMetadataID() const { return SubclassID; } /// \brief User-friendly dump. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + /// + /// Note: this uses an explicit overload instead of default arguments so that + /// the nullptr version is easy to call from a debugger. + /// + /// @{ void dump() const; - void print(raw_ostream &OS) const; - void printAsOperand(raw_ostream &OS, bool PrintType = true, - const Module *M = nullptr) const; + void dump(const Module *M) const; + /// @} + + /// \brief Print. + /// + /// Prints definition of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + void print(raw_ostream &OS, const Module *M = nullptr) const; + + /// \brief Print as operand. + /// + /// Prints reference of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const; }; #define HANDLE_METADATA(CLASS) class CLASS; #include "llvm/IR/Metadata.def" +// Provide specializations of isa so that we don't need definitions of +// subclasses to see if the metadata is a subclass. +#define HANDLE_METADATA_LEAF(CLASS) \ + template <> struct isa_impl<CLASS, Metadata> { \ + static inline bool doit(const Metadata &MD) { \ + return MD.getMetadataID() == Metadata::CLASS##Kind; \ + } \ + }; +#include "llvm/IR/Metadata.def" + inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { MD.print(OS); return OS; diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 62f4194..ac60c8e 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -219,14 +219,7 @@ private: std::string TargetTriple; ///< Platform target triple Module compiled on ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - - // We need to keep the string because the C API expects us to own the string - // representation. - // Since we have it, we also use an empty string to represent a module without - // a DataLayout. If it has a DataLayout, these variables are in sync and the - // string is just a cache of getDataLayout()->getStringRepresentation(). - std::string DataLayoutStr; - DataLayout DL; + DataLayout DL; ///< DataLayout associated with the module friend class Constant; @@ -256,10 +249,12 @@ public: /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). - const std::string &getDataLayoutStr() const { return DataLayoutStr; } + const std::string getDataLayoutStr() const { + return DL.getStringRepresentation(); + } /// Get the data layout for the module's target platform. - const DataLayout *getDataLayout() const; + const DataLayout &getDataLayout() const; /// Get the target triple which is a string describing the target host. /// @returns a string containing the target triple. @@ -293,12 +288,13 @@ public: /// Set the data layout void setDataLayout(StringRef Desc); - void setDataLayout(const DataLayout *Other); + void setDataLayout(const DataLayout &Other); /// Set the target triple. void setTargetTriple(StringRef T) { TargetTriple = T; } /// Set the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; if (!GlobalScopeAsm.empty() && @@ -306,8 +302,8 @@ public: GlobalScopeAsm += '\n'; } - /// Append to the module-scope inline assembly blocks, automatically inserting - /// a separating newline if necessary. + /// Append to the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. void appendModuleInlineAsm(StringRef Asm) { GlobalScopeAsm += Asm; if (!GlobalScopeAsm.empty() && @@ -506,6 +502,8 @@ public: /// Materializer. std::error_code materializeAllPermanently(); + std::error_code materializeMetadata(); + /// @} /// @name Direct access to the globals list, functions list, and symbol table /// @{ diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h index a9cdfc3..ab7bed6 100644 --- a/include/llvm/IR/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -189,7 +189,7 @@ public: } Instruction *CreateGetElementPtr(Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::Create(C, IdxList); + return GetElementPtrInst::Create(nullptr, C, IdxList); } Constant *CreateInBoundsGetElementPtr(Constant *C, @@ -204,7 +204,7 @@ public: } Instruction *CreateInBoundsGetElementPtr(Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::CreateInBounds(C, IdxList); + return GetElementPtrInst::CreateInBounds(nullptr, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 46935ce..c87f89c 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -400,6 +400,11 @@ public: return getPointerOperand()->getType(); } + Type *getSourceElementType() const { + return cast<SequentialType>(getPointerOperandType()->getScalarType()) + ->getElementType(); + } + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { return getPointerOperandType()->getPointerAddressSpace(); diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index c92e7c9..3c24e72 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -46,6 +46,7 @@ #include "llvm/IR/PassManagerInternal.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/type_traits.h" #include <list> #include <memory> @@ -471,6 +472,12 @@ private: dbgs() << "Running analysis: " << P.name() << "\n"; AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(PassID, P.run(IR, this)); + + // P.run may have inserted elements into AnalysisResults and invalidated + // RI. + RI = AnalysisResults.find(std::make_pair(PassID, &IR)); + assert(RI != AnalysisResults.end() && "we just inserted it!"); + RI->second = std::prev(ResultList.end()); } diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h index 297f5f4..92de10b 100644 --- a/include/llvm/IR/PassManagerInternal.h +++ b/include/llvm/IR/PassManagerInternal.h @@ -19,6 +19,7 @@ #define LLVM_IR_PASSMANAGERINTERNAL_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" namespace llvm { diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index b7213a6..8217ef7 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -450,7 +450,7 @@ public: /// /// Test if this value is always a pointer to allocated and suitably aligned /// memory for a simple load or store. - bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; + bool isDereferenceablePointer(const DataLayout &DL) const; /// \brief Translate PHI node to its predecessor from the given basic block. /// diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 43bd123..89039d2 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -56,20 +56,9 @@ bool verifyModule(const Module &M, raw_ostream *OS = nullptr); /// printed to stderr, and by default they are fatal. You can override that by /// passing \c false to \p FatalErrors. /// -/// Note that this creates a pass suitable for the legacy pass manager. It has nothing to do with \c VerifierPass. -FunctionPass *createVerifierPass(bool FatalErrors = true); - -/// \brief Create a debug-info verifier pass. -/// -/// Check a module for validity of debug info. This is essentially a pass -/// wrapped around the debug-info parts of \a verifyModule(). When the pass -/// detects a verification error it is always printed to stderr, and by default -/// they are fatal. You can override that by passing \c false to \p -/// FatalErrors. -/// /// Note that this creates a pass suitable for the legacy pass manager. It has /// nothing to do with \c VerifierPass. -ModulePass *createDebugInfoVerifierPass(bool FatalErrors = true); +FunctionPass *createVerifierPass(bool FatalErrors = true); class VerifierPass { bool FatalErrors; |