diff options
Diffstat (limited to 'lib/IR')
-rw-r--r-- | lib/IR/AsmWriter.cpp | 2 | ||||
-rw-r--r-- | lib/IR/AttributeImpl.h | 217 | ||||
-rw-r--r-- | lib/IR/Attributes.cpp | 143 | ||||
-rw-r--r-- | lib/IR/AutoUpgrade.cpp | 10 | ||||
-rw-r--r-- | lib/IR/ConstantFold.cpp | 13 | ||||
-rw-r--r-- | lib/IR/Constants.cpp | 31 | ||||
-rw-r--r-- | lib/IR/DIBuilder.cpp | 144 | ||||
-rw-r--r-- | lib/IR/DataLayout.cpp | 14 | ||||
-rw-r--r-- | lib/IR/DebugInfo.cpp | 323 | ||||
-rw-r--r-- | lib/IR/Function.cpp | 10 | ||||
-rw-r--r-- | lib/IR/GCOV.cpp | 16 | ||||
-rw-r--r-- | lib/IR/Instructions.cpp | 125 | ||||
-rw-r--r-- | lib/IR/Metadata.cpp | 4 | ||||
-rw-r--r-- | lib/IR/Module.cpp | 16 | ||||
-rw-r--r-- | lib/IR/PassManager.cpp | 12 | ||||
-rw-r--r-- | lib/IR/PassRegistry.cpp | 21 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 308 |
17 files changed, 910 insertions, 499 deletions
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 4a5bf15..f275305 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -84,6 +84,8 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::MSP430_INTR: Out << "msp430_intrcc"; break; case CallingConv::PTX_Kernel: Out << "ptx_kernel"; break; case CallingConv::PTX_Device: Out << "ptx_device"; break; + case CallingConv::X86_64_SysV: Out << "x86_64_sysvcc"; break; + case CallingConv::X86_64_Win64: Out << "x86_64_win64cc"; break; } } diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index 0b6228b..9da3f96 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -27,97 +27,30 @@ class LLVMContext; //===----------------------------------------------------------------------===// /// \class -/// \brief A set of classes that contain the kind and (optional) value of the -/// attribute object. There are three main categories: enum attribute entries, -/// represented by Attribute::AttrKind; alignment attribute entries; and string -/// attribute enties, which are for target-dependent attributes. -class AttributeEntry { - unsigned char KindID; +/// \brief This class represents a single, uniqued attribute. That attribute +/// could be a single enum, a tuple, or a string. +class AttributeImpl : public FoldingSetNode { + unsigned char KindID; ///< Holds the AttrEntryKind of the attribute + + // AttributesImpl is uniqued, these should not be publicly available. + void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION; + AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION; + protected: enum AttrEntryKind { EnumAttrEntry, AlignAttrEntry, StringAttrEntry }; -public: - AttributeEntry(AttrEntryKind Kind) - : KindID(Kind) {} - virtual ~AttributeEntry() {} - unsigned getKindID() const { return KindID; } + AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} - static inline bool classof(const AttributeEntry *) { return true; } -}; - -class EnumAttributeEntry : public AttributeEntry { - Attribute::AttrKind Kind; public: - EnumAttributeEntry(Attribute::AttrKind Kind) - : AttributeEntry(EnumAttrEntry), Kind(Kind) {} - - Attribute::AttrKind getEnumKind() const { return Kind; } - - static inline bool classof(const AttributeEntry *AE) { - return AE->getKindID() == EnumAttrEntry; - } - static inline bool classof(const EnumAttributeEntry *) { return true; } -}; + virtual ~AttributeImpl(); -class AlignAttributeEntry : public AttributeEntry { - Attribute::AttrKind Kind; - unsigned Align; -public: - AlignAttributeEntry(Attribute::AttrKind Kind, unsigned Align) - : AttributeEntry(AlignAttrEntry), Kind(Kind), Align(Align) {} - - Attribute::AttrKind getEnumKind() const { return Kind; } - unsigned getAlignment() const { return Align; } - - static inline bool classof(const AttributeEntry *AE) { - return AE->getKindID() == AlignAttrEntry; - } - static inline bool classof(const AlignAttributeEntry *) { return true; } -}; - -class StringAttributeEntry : public AttributeEntry { - std::string Kind; - std::string Val; -public: - StringAttributeEntry(StringRef Kind, StringRef Val = StringRef()) - : AttributeEntry(StringAttrEntry), Kind(Kind), Val(Val) {} - - StringRef getStringKind() const { return Kind; } - StringRef getStringValue() const { return Val; } - - static inline bool classof(const AttributeEntry *AE) { - return AE->getKindID() == StringAttrEntry; - } - static inline bool classof(const StringAttributeEntry *) { return true; } -}; - -//===----------------------------------------------------------------------===// -/// \class -/// \brief This class represents a single, uniqued attribute. That attribute -/// could be a single enum, a tuple, or a string. -class AttributeImpl : public FoldingSetNode { - LLVMContext &Context; ///< Global context for uniquing objects - - AttributeEntry *Entry; ///< Holds the kind and value of the attribute - - // AttributesImpl is uniqued, these should not be publicly available. - void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION; - AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION; -public: - AttributeImpl(LLVMContext &C, Attribute::AttrKind Kind); - AttributeImpl(LLVMContext &C, Attribute::AttrKind Kind, unsigned Align); - AttributeImpl(LLVMContext &C, StringRef Kind, StringRef Val = StringRef()); - ~AttributeImpl(); - - LLVMContext &getContext() { return Context; } - - bool isEnumAttribute() const; - bool isAlignAttribute() const; - bool isStringAttribute() const; + bool isEnumAttribute() const { return KindID == EnumAttrEntry; } + bool isAlignAttribute() const { return KindID == AlignAttrEntry; } + bool isStringAttribute() const { return KindID == StringAttrEntry; } bool hasAttribute(Attribute::AttrKind A) const; bool hasAttribute(StringRef Kind) const; @@ -155,13 +88,63 @@ public: //===----------------------------------------------------------------------===// /// \class +/// \brief A set of classes that contain the value of the +/// attribute object. There are three main categories: enum attribute entries, +/// represented by Attribute::AttrKind; alignment attribute entries; and string +/// attribute enties, which are for target-dependent attributes. + +class EnumAttributeImpl : public AttributeImpl { + Attribute::AttrKind Kind; + +protected: + EnumAttributeImpl(AttrEntryKind ID, Attribute::AttrKind Kind) + : AttributeImpl(ID), Kind(Kind) {} + +public: + EnumAttributeImpl(Attribute::AttrKind Kind) + : AttributeImpl(EnumAttrEntry), Kind(Kind) {} + + Attribute::AttrKind getEnumKind() const { return Kind; } +}; + +class AlignAttributeImpl : public EnumAttributeImpl { + unsigned Align; + +public: + AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align) + : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) { + assert( + (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) && + "Wrong kind for alignment attribute!"); + } + + unsigned getAlignment() const { return Align; } +}; + +class StringAttributeImpl : public AttributeImpl { + std::string Kind; + std::string Val; + +public: + StringAttributeImpl(StringRef Kind, StringRef Val = StringRef()) + : AttributeImpl(StringAttrEntry), Kind(Kind), Val(Val) {} + + StringRef getStringKind() const { return Kind; } + StringRef getStringValue() const { return Val; } +}; + +//===----------------------------------------------------------------------===// +/// \class /// \brief This class represents a group of attributes that apply to one /// element: function, return type, or parameter. class AttributeSetNode : public FoldingSetNode { - SmallVector<Attribute, 4> AttrList; + unsigned NumAttrs; ///< Number of attributes in this node. - AttributeSetNode(ArrayRef<Attribute> Attrs) - : AttrList(Attrs.begin(), Attrs.end()) {} + AttributeSetNode(ArrayRef<Attribute> Attrs) : NumAttrs(Attrs.size()) { + // There's memory after the node where we can store the entries in. + std::copy(Attrs.begin(), Attrs.end(), + reinterpret_cast<Attribute *>(this + 1)); + } // AttributesSetNode is uniqued, these should not be publicly available. void operator=(const AttributeSetNode &) LLVM_DELETED_FUNCTION; @@ -171,7 +154,7 @@ public: bool hasAttribute(Attribute::AttrKind Kind) const; bool hasAttribute(StringRef Kind) const; - bool hasAttributes() const { return !AttrList.empty(); } + bool hasAttributes() const { return NumAttrs != 0; } Attribute getAttribute(Attribute::AttrKind Kind) const; Attribute getAttribute(StringRef Kind) const; @@ -180,17 +163,12 @@ public: unsigned getStackAlignment() const; std::string getAsString(bool InAttrGrp) const; - typedef SmallVectorImpl<Attribute>::iterator iterator; - typedef SmallVectorImpl<Attribute>::const_iterator const_iterator; - - iterator begin() { return AttrList.begin(); } - iterator end() { return AttrList.end(); } - - const_iterator begin() const { return AttrList.begin(); } - const_iterator end() const { return AttrList.end(); } + typedef const Attribute *iterator; + iterator begin() const { return reinterpret_cast<iterator>(this + 1); } + iterator end() const { return begin() + NumAttrs; } void Profile(FoldingSetNodeID &ID) const { - Profile(ID, AttrList); + Profile(ID, makeArrayRef(begin(), end())); } static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) { for (unsigned I = 0, E = AttrList.size(); I != E; ++I) @@ -208,58 +186,67 @@ class AttributeSetImpl : public FoldingSetNode { LLVMContext &Context; typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair; - SmallVector<IndexAttrPair, 4> AttrNodes; + unsigned NumAttrs; ///< Number of entries in this set. + + /// \brief Return a pointer to the IndexAttrPair for the specified slot. + const IndexAttrPair *getNode(unsigned Slot) const { + return reinterpret_cast<const IndexAttrPair *>(this + 1) + Slot; + } // AttributesSet is uniqued, these should not be publicly available. void operator=(const AttributeSetImpl &) LLVM_DELETED_FUNCTION; AttributeSetImpl(const AttributeSetImpl &) LLVM_DELETED_FUNCTION; public: AttributeSetImpl(LLVMContext &C, - ArrayRef<std::pair<unsigned, AttributeSetNode*> > attrs) - : Context(C), AttrNodes(attrs.begin(), attrs.end()) {} + ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs) + : Context(C), NumAttrs(Attrs.size()) { +#ifndef NDEBUG + if (Attrs.size() >= 2) { + for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1, + *e = Attrs.end(); + i != e; ++i) { + assert((i-1)->first <= i->first && "Attribute set not ordered!"); + } + } +#endif + // There's memory after the node where we can store the entries in. + std::copy(Attrs.begin(), Attrs.end(), + reinterpret_cast<IndexAttrPair *>(this + 1)); + } /// \brief Get the context that created this AttributeSetImpl. LLVMContext &getContext() { return Context; } /// \brief Return the number of attributes this AttributeSet contains. - unsigned getNumAttributes() const { return AttrNodes.size(); } + unsigned getNumAttributes() const { return NumAttrs; } /// \brief Get the index of the given "slot" in the AttrNodes list. This index /// is the index of the return, parameter, or function object that the /// attributes are applied to, not the index into the AttrNodes list where the /// attributes reside. unsigned getSlotIndex(unsigned Slot) const { - return AttrNodes[Slot].first; + return getNode(Slot)->first; } /// \brief Retrieve the attributes for the given "slot" in the AttrNode list. /// \p Slot is an index into the AttrNodes list, not the index of the return / /// parameter/ function which the attributes apply to. AttributeSet getSlotAttributes(unsigned Slot) const { - return AttributeSet::get(Context, AttrNodes[Slot]); + return AttributeSet::get(Context, *getNode(Slot)); } /// \brief Retrieve the attribute set node for the given "slot" in the /// AttrNode list. AttributeSetNode *getSlotNode(unsigned Slot) const { - return AttrNodes[Slot].second; + return getNode(Slot)->second; } - typedef AttributeSetNode::iterator iterator; - typedef AttributeSetNode::const_iterator const_iterator; - - iterator begin(unsigned Slot) - { return AttrNodes[Slot].second->begin(); } - iterator end(unsigned Slot) - { return AttrNodes[Slot].second->end(); } - - const_iterator begin(unsigned Slot) const - { return AttrNodes[Slot].second->begin(); } - const_iterator end(unsigned Slot) const - { return AttrNodes[Slot].second->end(); } + typedef AttributeSetNode::iterator iterator; + iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); } + iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); } void Profile(FoldingSetNodeID &ID) const { - Profile(ID, AttrNodes); + Profile(ID, makeArrayRef(getNode(0), getNumAttributes())); } static void Profile(FoldingSetNodeID &ID, ArrayRef<std::pair<unsigned, AttributeSetNode*> > Nodes) { @@ -271,6 +258,8 @@ public: // FIXME: This atrocity is temporary. uint64_t Raw(unsigned Index) const; + + void dump() const; }; } // end llvm namespace diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index e48ebb1..f466d16 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -43,9 +43,10 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, if (!PA) { // If we didn't find any existing attributes of the same shape then create a // new one and insert it. - PA = !Val ? - new AttributeImpl(Context, Kind) : - new AttributeImpl(Context, Kind, Val); + if (!Val) + PA = new EnumAttributeImpl(Kind); + else + PA = new AlignAttributeImpl(Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } @@ -65,7 +66,7 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { if (!PA) { // If we didn't find any existing attributes of the same shape then create a // new one and insert it. - PA = new AttributeImpl(Context, Kind, Val); + PA = new StringAttributeImpl(Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } @@ -103,24 +104,28 @@ bool Attribute::isStringAttribute() const { } Attribute::AttrKind Attribute::getKindAsEnum() const { + if (!pImpl) return None; assert((isEnumAttribute() || isAlignAttribute()) && "Invalid attribute type to get the kind as an enum!"); return pImpl ? pImpl->getKindAsEnum() : None; } uint64_t Attribute::getValueAsInt() const { + if (!pImpl) return 0; assert(isAlignAttribute() && "Expected the attribute to be an alignment attribute!"); return pImpl ? pImpl->getValueAsInt() : 0; } StringRef Attribute::getKindAsString() const { + if (!pImpl) return StringRef(); assert(isStringAttribute() && "Invalid attribute type to get the kind as a string!"); return pImpl ? pImpl->getKindAsString() : StringRef(); } StringRef Attribute::getValueAsString() const { + if (!pImpl) return StringRef(); assert(isStringAttribute() && "Invalid attribute type to get the value as a string!"); return pImpl ? pImpl->getValueAsString() : StringRef(); @@ -157,6 +162,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "sanitize_address"; if (hasAttribute(Attribute::AlwaysInline)) return "alwaysinline"; + if (hasAttribute(Attribute::Builtin)) + return "builtin"; if (hasAttribute(Attribute::ByVal)) return "byval"; if (hasAttribute(Attribute::InlineHint)) @@ -277,35 +284,7 @@ bool Attribute::operator<(Attribute A) const { // AttributeImpl Definition //===----------------------------------------------------------------------===// -AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind Kind) - : Context(C), Entry(new EnumAttributeEntry(Kind)) {} - -AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind Kind, - unsigned Align) - : Context(C) { - assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) && - "Wrong kind for alignment attribute!"); - Entry = new AlignAttributeEntry(Kind, Align); -} - -AttributeImpl::AttributeImpl(LLVMContext &C, StringRef Kind, StringRef Val) - : Context(C), Entry(new StringAttributeEntry(Kind, Val)) {} - -AttributeImpl::~AttributeImpl() { - delete Entry; -} - -bool AttributeImpl::isEnumAttribute() const { - return isa<EnumAttributeEntry>(Entry); -} - -bool AttributeImpl::isAlignAttribute() const { - return isa<AlignAttributeEntry>(Entry); -} - -bool AttributeImpl::isStringAttribute() const { - return isa<StringAttributeEntry>(Entry); -} +AttributeImpl::~AttributeImpl() {} bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { if (isStringAttribute()) return false; @@ -318,21 +297,23 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const { } Attribute::AttrKind AttributeImpl::getKindAsEnum() const { - if (EnumAttributeEntry *E = dyn_cast<EnumAttributeEntry>(Entry)) - return E->getEnumKind(); - return cast<AlignAttributeEntry>(Entry)->getEnumKind(); + assert(isEnumAttribute() || isAlignAttribute()); + return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); } uint64_t AttributeImpl::getValueAsInt() const { - return cast<AlignAttributeEntry>(Entry)->getAlignment(); + assert(isAlignAttribute()); + return static_cast<const AlignAttributeImpl *>(this)->getAlignment(); } StringRef AttributeImpl::getKindAsString() const { - return cast<StringAttributeEntry>(Entry)->getStringKind(); + assert(isStringAttribute()); + return static_cast<const StringAttributeImpl *>(this)->getStringKind(); } StringRef AttributeImpl::getValueAsString() const { - return cast<StringAttributeEntry>(Entry)->getStringValue(); + assert(isStringAttribute()); + return static_cast<const StringAttributeImpl *>(this)->getStringValue(); } bool AttributeImpl::operator<(const AttributeImpl &AI) const { @@ -399,6 +380,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::NoBuiltin: return 1ULL << 38; case Attribute::Returned: return 1ULL << 39; case Attribute::Cold: return 1ULL << 40; + case Attribute::Builtin: return 1ULL << 41; } llvm_unreachable("Unsupported attribute type"); } @@ -430,7 +412,10 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, // If we didn't find any existing attributes of the same shape then create a // new one and insert it. if (!PA) { - PA = new AttributeSetNode(SortedAttrs); + // Coallocate entries after the AttributeSetNode itself. + void *Mem = ::operator new(sizeof(AttributeSetNode) + + sizeof(Attribute) * SortedAttrs.size()); + PA = new (Mem) AttributeSetNode(SortedAttrs); pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint); } @@ -439,48 +424,42 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, } bool AttributeSetNode::hasAttribute(Attribute::AttrKind Kind) const { - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) + for (iterator I = begin(), E = end(); I != E; ++I) if (I->hasAttribute(Kind)) return true; return false; } bool AttributeSetNode::hasAttribute(StringRef Kind) const { - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) + for (iterator I = begin(), E = end(); I != E; ++I) if (I->hasAttribute(Kind)) return true; return false; } Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) + for (iterator I = begin(), E = end(); I != E; ++I) if (I->hasAttribute(Kind)) return *I; return Attribute(); } Attribute AttributeSetNode::getAttribute(StringRef Kind) const { - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) + for (iterator I = begin(), E = end(); I != E; ++I) if (I->hasAttribute(Kind)) return *I; return Attribute(); } unsigned AttributeSetNode::getAlignment() const { - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) + for (iterator I = begin(), E = end(); I != E; ++I) if (I->hasAttribute(Attribute::Alignment)) return I->getAlignment(); return 0; } unsigned AttributeSetNode::getStackAlignment() const { - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) + for (iterator I = begin(), E = end(); I != E; ++I) if (I->hasAttribute(Attribute::StackAlignment)) return I->getStackAlignment(); return 0; @@ -488,9 +467,8 @@ unsigned AttributeSetNode::getStackAlignment() const { std::string AttributeSetNode::getAsString(bool InAttrGrp) const { std::string Str; - for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ++I) { - if (I != AttrList.begin()) + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I != begin()) Str += ' '; Str += I->getAsString(InAttrGrp); } @@ -504,10 +482,10 @@ std::string AttributeSetNode::getAsString(bool InAttrGrp) const { uint64_t AttributeSetImpl::Raw(unsigned Index) const { for (unsigned I = 0, E = getNumAttributes(); I != E; ++I) { if (getSlotIndex(I) != Index) continue; - const AttributeSetNode *ASN = AttrNodes[I].second; + const AttributeSetNode *ASN = getSlotNode(I); uint64_t Mask = 0; - for (AttributeSetNode::const_iterator II = ASN->begin(), + for (AttributeSetNode::iterator II = ASN->begin(), IE = ASN->end(); II != IE; ++II) { Attribute Attr = *II; @@ -530,6 +508,10 @@ uint64_t AttributeSetImpl::Raw(unsigned Index) const { return 0; } +void AttributeSetImpl::dump() const { + AttributeSet(const_cast<AttributeSetImpl *>(this)).dump(); +} + //===----------------------------------------------------------------------===// // AttributeSet Construction and Mutation Methods //===----------------------------------------------------------------------===// @@ -547,7 +529,11 @@ AttributeSet::getImpl(LLVMContext &C, // If we didn't find any existing attributes of the same shape then // create a new one and insert it. if (!PA) { - PA = new AttributeSetImpl(C, Attrs); + // Coallocate entries after the AttributeSetImpl itself. + void *Mem = ::operator new(sizeof(AttributeSetImpl) + + sizeof(std::pair<unsigned, AttributeSetNode *>) * + Attrs.size()); + PA = new (Mem) AttributeSetImpl(C, Attrs); pImpl->AttrsLists.InsertNode(PA, InsertPoint); } @@ -639,12 +625,30 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) { if (Attrs.empty()) return AttributeSet(); + if (Attrs.size() == 1) return Attrs[0]; SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrNodeVec; - for (unsigned I = 0, E = Attrs.size(); I != E; ++I) { - AttributeSet AS = Attrs[I]; - if (!AS.pImpl) continue; - AttrNodeVec.append(AS.pImpl->AttrNodes.begin(), AS.pImpl->AttrNodes.end()); + AttributeSetImpl *A0 = Attrs[0].pImpl; + if (A0) + AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumAttributes())); + // Copy all attributes from Attrs into AttrNodeVec while keeping AttrNodeVec + // ordered by index. Because we know that each list in Attrs is ordered by + // index we only need to merge each successive list in rather than doing a + // full sort. + for (unsigned I = 1, E = Attrs.size(); I != E; ++I) { + AttributeSetImpl *AS = Attrs[I].pImpl; + if (!AS) continue; + SmallVector<std::pair<unsigned, AttributeSetNode *>, 8>::iterator + ANVI = AttrNodeVec.begin(), ANVE; + for (const AttributeSetImpl::IndexAttrPair + *AI = AS->getNode(0), + *AE = AS->getNode(AS->getNumAttributes()); + AI != AE; ++AI) { + ANVE = AttrNodeVec.end(); + while (ANVI != ANVE && ANVI->first <= AI->first) + ++ANVI; + ANVI = AttrNodeVec.insert(ANVI, *AI) + 1; + } } return getImpl(C, AttrNodeVec); @@ -663,6 +667,13 @@ AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, return addAttributes(C, Index, AttributeSet::get(C, Index, B)); } +AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, + StringRef Kind, StringRef Value) const { + llvm::AttrBuilder B; + B.addAttribute(Kind, Value); + return addAttributes(C, Index, AttributeSet::get(C, Index, B)); +} + AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const { if (!pImpl) return Attrs; @@ -697,7 +708,7 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index, for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) if (Attrs.getSlotIndex(I) == Index) { - for (AttributeSetImpl::const_iterator II = Attrs.pImpl->begin(I), + for (AttributeSetImpl::iterator II = Attrs.pImpl->begin(I), IE = Attrs.pImpl->end(I); II != IE; ++II) B.addAttribute(*II); break; @@ -818,7 +829,7 @@ bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { if (pImpl == 0) return false; for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) - for (AttributeSetImpl::const_iterator II = pImpl->begin(I), + for (AttributeSetImpl::iterator II = pImpl->begin(I), IE = pImpl->end(I); II != IE; ++II) if (II->hasAttribute(Attr)) return true; @@ -934,7 +945,7 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) { if (pImpl->getSlotIndex(I) != Index) continue; - for (AttributeSetImpl::const_iterator II = pImpl->begin(I), + for (AttributeSetImpl::iterator II = pImpl->begin(I), IE = pImpl->end(I); II != IE; ++II) addAttribute(*II); @@ -1154,6 +1165,8 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { .addAttribute(Attribute::Nest) .addAttribute(Attribute::NoAlias) .addAttribute(Attribute::NoCapture) + .addAttribute(Attribute::ReadNone) + .addAttribute(Attribute::ReadOnly) .addAttribute(Attribute::StructRet); return AttributeSet::get(Ty->getContext(), Index, Incompatible); diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp index f237537..a4f5289 100644 --- a/lib/IR/AutoUpgrade.cpp +++ b/lib/IR/AutoUpgrade.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the auto-upgrade helper functions +// This file implements the auto-upgrade helper functions // //===----------------------------------------------------------------------===// @@ -55,14 +55,14 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { case 'a': { if (Name.startswith("arm.neon.vclz")) { Type* args[2] = { - F->arg_begin()->getType(), + F->arg_begin()->getType(), Type::getInt1Ty(F->getContext()) }; // Can't use Intrinsic::getDeclaration here as it adds a ".i1" to // the end of the name. Change name from llvm.arm.neon.vclz.* to // llvm.ctlz.* FunctionType* fType = FunctionType::get(F->getReturnType(), args, false); - NewFn = Function::Create(fType, F->getLinkage(), + NewFn = Function::Create(fType, F->getLinkage(), "llvm.ctlz." + Name.substr(14), F->getParent()); return true; } @@ -369,8 +369,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { } } -// This tests each Function to determine if it needs upgrading. When we find -// one we are interested in, we then upgrade all calls to reflect the new +// This tests each Function to determine if it needs upgrading. When we find +// one we are interested in, we then upgrade all calls to reflect the new // function. void llvm::UpgradeCallsToIntrinsic(Function* F) { assert(F && "Illegal attempt to upgrade a non-existent intrinsic."); diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index bf93d4f..8c5a983 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -75,7 +75,7 @@ static unsigned foldConstantCastPair( unsigned opc, ///< opcode of the second cast constant expression ConstantExpr *Op, ///< the first cast constant expression - Type *DstTy ///< desintation type of the first cast + Type *DstTy ///< destination type of the first cast ) { assert(Op && Op->isCast() && "Can't fold cast of cast without a cast!"); assert(DstTy && DstTy->isFirstClassType() && "Invalid cast destination type"); @@ -87,13 +87,14 @@ foldConstantCastPair( Instruction::CastOps firstOp = Instruction::CastOps(Op->getOpcode()); Instruction::CastOps secondOp = Instruction::CastOps(opc); - // Assume that pointers are never more than 64 bits wide. + // Assume that pointers are never more than 64 bits wide, and only use this + // for the middle type. Otherwise we could end up folding away illegal + // bitcasts between address spaces with different sizes. IntegerType *FakeIntPtrTy = Type::getInt64Ty(DstTy->getContext()); // Let CastInst::isEliminableCastPair do the heavy lifting. return CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, DstTy, - FakeIntPtrTy, FakeIntPtrTy, - FakeIntPtrTy); + 0, FakeIntPtrTy, 0); } static Constant *FoldBitCast(Constant *V, Type *DestTy) { @@ -1857,9 +1858,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, if (CE1Inverse == CE1Op0) { // Check whether we can safely truncate the right hand side. Constant *C2Inverse = ConstantExpr::getTrunc(C2, CE1Op0->getType()); - if (ConstantExpr::getZExt(C2Inverse, C2->getType()) == C2) { + if (ConstantExpr::getCast(CE1->getOpcode(), C2Inverse, + C2->getType()) == C2) return ConstantExpr::getICmp(pred, CE1Inverse, C2Inverse); - } } } } diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index d370d40..9067b34 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -1389,7 +1389,7 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { BasicBlock *NewBB = getBasicBlock(); if (U == &Op<0>()) - NewF = cast<Function>(To); + NewF = cast<Function>(To->stripPointerCasts()); else NewBB = cast<BasicBlock>(To); @@ -1954,14 +1954,22 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, ArrayRef<unsigned> Idxs) { + assert(Agg->getType()->isFirstClassType() && + "Non-first-class type for constant insertvalue expression"); + assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs) == Val->getType() && "insertvalue indices invalid!"); - assert(Agg->getType()->isFirstClassType() && - "Non-first-class type for constant insertvalue expression"); - Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs); - assert(FC && "insertvalue constant expr couldn't be folded!"); - return FC; + Type *ReqTy = Val->getType(); + + if (Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs)) + return FC; + + Constant *ArgVec[] = { Agg, Val }; + const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); + + LLVMContextImpl *pImpl = Agg->getContext().pImpl; + return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } Constant *ConstantExpr::getExtractValue(Constant *Agg, @@ -1975,9 +1983,14 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, assert(Agg->getType()->isFirstClassType() && "Non-first-class type for constant extractvalue expression"); - Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs); - assert(FC && "ExtractValue constant expr couldn't be folded!"); - return FC; + if (Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs)) + return FC; + + Constant *ArgVec[] = { Agg }; + const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); + + LLVMContextImpl *pImpl = Agg->getContext().pImpl; + return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } Constant *ConstantExpr::getNeg(Constant *C, bool HasNUW, bool HasNSW) { diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 6c274da..3005f77 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -30,7 +30,7 @@ static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { } DIBuilder::DIBuilder(Module &m) - : M(m), VMContext(M.getContext()), TheCU(0), TempEnumTypes(0), + : M(m), VMContext(M.getContext()), TempEnumTypes(0), TempRetainTypes(0), TempSubprograms(0), TempGVs(0), DeclareFn(0), ValueFn(0) {} @@ -86,10 +86,11 @@ static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename, /// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. -void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, - StringRef Directory, StringRef Producer, - bool isOptimized, StringRef Flags, - unsigned RunTimeVer, StringRef SplitName) { +DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, + StringRef Directory, + StringRef Producer, bool isOptimized, + StringRef Flags, unsigned RunTimeVer, + StringRef SplitName) { assert(((Lang <= dwarf::DW_LANG_Python && Lang >= dwarf::DW_LANG_C89) || (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && "Invalid Language tag"); @@ -121,11 +122,14 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, TempImportedModules, MDString::get(VMContext, SplitName) }; - TheCU = DICompileUnit(MDNode::get(VMContext, Elts)); + + MDNode *CUNode = MDNode::get(VMContext, Elts); // Create a named metadata so that it is easier to find cu in a module. NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); - NMD->addOperand(TheCU); + NMD->addOperand(CUNode); + + return DICompileUnit(CUNode); } static DIImportedEntity @@ -198,7 +202,7 @@ DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { } /// createEnumerator - Create a single enumerator value. -DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { +DIEnumerator DIBuilder::createEnumerator(StringRef Name, int64_t Val) { assert(!Name.empty() && "Unable to create enumerator without name"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), @@ -208,15 +212,15 @@ DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { return DIEnumerator(MDNode::get(VMContext, Elts)); } -/// createNullPtrType - Create C++0x nullptr type. -DIBasicType DIBuilder::createNullPtrType(StringRef Name) { +/// \brief Create a DWARF unspecified type. +DIBasicType DIBuilder::createUnspecifiedType(StringRef Name) { assert(!Name.empty() && "Unable to create type without name"); - // nullptr is encoded in DIBasicType format. Line number, filename, - // ,size, alignment, offset and flags are always empty here. + // Unspecified types are encoded in DIBasicType format. Line number, filename, + // size, alignment, offset and flags are always empty here. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type), NULL, // Filename - NULL, //TheCU, + NULL, // Unused MDString::get(VMContext, Name), ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size @@ -228,6 +232,11 @@ DIBasicType DIBuilder::createNullPtrType(StringRef Name) { return DIBasicType(MDNode::get(VMContext, Elts)); } +/// \brief Create C++11 nullptr type. +DIBasicType DIBuilder::createNullPtrType() { + return createUnspecifiedType("decltype(nullptr)"); +} + /// createBasicType - Create debugging information entry for a basic /// type, e.g 'char'. DIBasicType @@ -239,7 +248,7 @@ DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_base_type), NULL, // File/directory name - NULL, //TheCU, + NULL, // Unused MDString::get(VMContext, Name), ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), @@ -258,7 +267,7 @@ DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { Value *Elts[] = { GetTagConstant(VMContext, Tag), NULL, // Filename - NULL, //TheCU, + NULL, // Unused MDString::get(VMContext, StringRef()), // Empty name. ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size @@ -278,7 +287,7 @@ DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), NULL, // Filename - NULL, //TheCU, + NULL, // Unused MDString::get(VMContext, Name), ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), @@ -296,7 +305,7 @@ DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy, Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_ptr_to_member_type), NULL, // Filename - NULL, //TheCU, + NULL, // Unused NULL, ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line ConstantInt::get(Type::getInt64Ty(VMContext), 0), @@ -312,7 +321,7 @@ DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy, /// createReferenceType - Create debugging information entry for a reference /// type. DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { - assert(RTy.Verify() && "Unable to create reference type"); + assert(RTy.isType() && "Unable to create reference type"); // References are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, Tag), @@ -333,7 +342,7 @@ DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo, DIDescriptor Context) { // typedefs are encoded in DIDerivedType format. - assert(Ty.Verify() && "Invalid typedef type!"); + assert(Ty.isType() && "Invalid typedef type!"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_typedef), File.getFileNode(), @@ -352,8 +361,8 @@ DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, /// createFriend - Create debugging information entry for a 'friend'. DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { // typedefs are encoded in DIDerivedType format. - assert(Ty.Verify() && "Invalid type!"); - assert(FriendTy.Verify() && "Invalid friend type!"); + assert(Ty.isType() && "Invalid type!"); + assert(FriendTy.isType() && "Invalid friend type!"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_friend), NULL, @@ -373,7 +382,7 @@ DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { /// inheritance relationship between two types. DIDerivedType DIBuilder::createInheritance( DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags) { - assert(Ty.Verify() && "Unable to create inheritance"); + assert(Ty.isType() && "Unable to create inheritance"); // TAG_inheritance is encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), @@ -530,15 +539,14 @@ DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, return DITemplateTypeParameter(MDNode::get(VMContext, Elts)); } -/// createTemplateValueParameter - Create debugging information for template -/// value parameter. DITemplateValueParameter -DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, - DIType Ty, Value *Val, - MDNode *File, unsigned LineNo, +DIBuilder::createTemplateValueParameter(unsigned Tag, DIDescriptor Context, + StringRef Name, DIType Ty, + Value *Val, MDNode *File, + unsigned LineNo, unsigned ColumnNo) { Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_template_value_parameter), + GetTagConstant(VMContext, Tag), getNonCompileUnitScope(Context), MDString::get(VMContext, Name), Ty, @@ -550,6 +558,38 @@ DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, return DITemplateValueParameter(MDNode::get(VMContext, Elts)); } +/// createTemplateValueParameter - Create debugging information for template +/// value parameter. +DITemplateValueParameter +DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, + DIType Ty, Value *Val, + MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + return createTemplateValueParameter(dwarf::DW_TAG_template_value_parameter, + Context, Name, Ty, Val, File, LineNo, + ColumnNo); +} + +DITemplateValueParameter +DIBuilder::createTemplateTemplateParameter(DIDescriptor Context, StringRef Name, + DIType Ty, StringRef Val, + MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + return createTemplateValueParameter( + dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty, + MDString::get(VMContext, Val), File, LineNo, ColumnNo); +} + +DITemplateValueParameter +DIBuilder::createTemplateParameterPack(DIDescriptor Context, StringRef Name, + DIType Ty, DIArray Val, + MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + return createTemplateValueParameter(dwarf::DW_TAG_GNU_template_parameter_pack, + Context, Name, Ty, Val, File, LineNo, + ColumnNo); +} + /// createClassType - Create debugging information entry for a class. DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, DIFile File, unsigned LineNumber, @@ -560,7 +600,7 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, DIArray Elements, MDNode *VTableHolder, MDNode *TemplateParams) { - assert((!Context || Context.Verify()) && + assert((!Context || Context.isScope() || Context.isType()) && "createClassType should be called with a valid Context"); // TAG_class_type is encoded in DICompositeType format. Value *Elts[] = { @@ -580,7 +620,8 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, TemplateParams }; DICompositeType R(MDNode::get(VMContext, Elts)); - assert(R.Verify() && "createClassType should return a verifiable DIType"); + assert(R.isCompositeType() && + "createClassType should return a DICompositeType"); return R; } @@ -612,7 +653,8 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context, NULL, }; DICompositeType R(MDNode::get(VMContext, Elts)); - assert(R.Verify() && "createStructType should return a verifiable DIType"); + assert(R.isCompositeType() && + "createStructType should return a DICompositeType"); return R; } @@ -699,7 +741,7 @@ DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_array_type), NULL, // Filename/Directory, - NULL, //TheCU, + NULL, // Unused MDString::get(VMContext, ""), ConstantInt::get(Type::getInt32Ty(VMContext), 0), ConstantInt::get(Type::getInt64Ty(VMContext), Size), @@ -722,7 +764,7 @@ DICompositeType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_array_type), NULL, // Filename/Directory, - NULL, //TheCU, + NULL, // Unused MDString::get(VMContext, ""), ConstantInt::get(Type::getInt32Ty(VMContext), 0), ConstantInt::get(Type::getInt64Ty(VMContext), Size), @@ -825,9 +867,10 @@ DIType DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) }; MDNode *Node = MDNode::getTemporary(VMContext, Elts); - assert(DIType(Node).Verify() && - "createForwardDecl result should be verifiable"); - return DIType(Node); + DIType RetTy(Node); + assert(RetTy.isType() && + "createForwardDecl result should be a DIType"); + return RetTy; } /// getOrCreateArray - Get a DIArray, create one if required. @@ -917,9 +960,9 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, bool AlwaysPreserve, unsigned Flags, unsigned ArgNo) { DIDescriptor Context(getNonCompileUnitScope(Scope)); - assert((!Context || Context.Verify()) && + assert((!Context || Context.isScope()) && "createLocalVariable should be called with a valid Context"); - assert(Ty.Verify() && + assert(Ty.isType() && "createLocalVariable should be called with a valid type"); Value *Elts[] = { GetTagConstant(VMContext, Tag), @@ -940,9 +983,10 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); FnLocals->addOperand(Node); } - assert(DIVariable(Node).Verify() && - "createLocalVariable should return a verifiable DIVariable"); - return DIVariable(Node); + DIVariable RetVar(Node); + assert(RetVar.isVariable() && + "createLocalVariable should return a valid DIVariable"); + return RetVar; } /// createComplexVariable - Create a new descriptor for the specified variable @@ -1010,7 +1054,7 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, if (isDefinition) AllSubprograms.push_back(Node); DISubprogram S(Node); - assert(S.Verify() && "createFunction should return a valid DISubprogram"); + assert(S.isSubprogram() && "createFunction should return a valid DISubprogram"); return S; } @@ -1058,7 +1102,7 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, if (isDefinition) AllSubprograms.push_back(Node); DISubprogram S(Node); - assert(S.Verify() && "createMethod should return a valid DISubprogram"); + assert(S.isSubprogram() && "createMethod should return a valid DISubprogram"); return S; } @@ -1097,7 +1141,7 @@ DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, unsigned Line, unsigned Col) { - // Defeat MDNode uniqing for lexical blocks by using unique id. + // Defeat MDNode uniquing for lexical blocks by using unique id. static unsigned int unique_id = 0; Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), @@ -1117,7 +1161,8 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, Instruction *InsertBefore) { assert(Storage && "no storage passed to dbg.declare"); - assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare"); + assert(VarInfo.isVariable() && + "empty or invalid DIVariable passed to dbg.declare"); if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); @@ -1129,7 +1174,8 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, BasicBlock *InsertAtEnd) { assert(Storage && "no storage passed to dbg.declare"); - assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare"); + assert(VarInfo.isVariable() && + "empty or invalid DIVariable passed to dbg.declare"); if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); @@ -1148,7 +1194,8 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, Instruction *InsertBefore) { assert(V && "no value passed to dbg.value"); - assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); + assert(VarInfo.isVariable() && + "empty or invalid DIVariable passed to dbg.value"); if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); @@ -1163,7 +1210,8 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, BasicBlock *InsertAtEnd) { assert(V && "no value passed to dbg.value"); - assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); + assert(VarInfo.isVariable() && + "empty or invalid DIVariable passed to dbg.value"); if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index d3669f9..d786d33 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -200,9 +200,7 @@ static unsigned inBytes(unsigned Bits) { } void DataLayout::parseSpecifier(StringRef Desc) { - while (!Desc.empty()) { - // Split at '-'. std::pair<StringRef, StringRef> Split = split(Desc, '-'); Desc = Split.second; @@ -482,7 +480,7 @@ std::string DataLayout::getStringRepresentation() const { addrSpaces.push_back(pib->first); } std::sort(addrSpaces.begin(), addrSpaces.end()); - for (SmallVector<unsigned, 8>::iterator asb = addrSpaces.begin(), + for (SmallVectorImpl<unsigned>::iterator asb = addrSpaces.begin(), ase = addrSpaces.end(); asb != ase; ++asb) { const PointerAlignElem &PI = Pointers.find(*asb)->second; OS << "-p"; @@ -509,6 +507,15 @@ std::string DataLayout::getStringRepresentation() const { return OS.str(); } +unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const { + assert(Ty->isPtrOrPtrVectorTy() && + "This should only be called with a pointer or pointer vector type"); + + if (Ty->isPointerTy()) + return getTypeSizeInBits(Ty); + + return getTypeSizeInBits(Ty->getScalarType()); +} /*! \param abi_or_pref Flag that determines which alignment is returned. true @@ -582,7 +589,6 @@ unsigned DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const { return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, 0); } - unsigned DataLayout::getCallFrameTypeAlignment(Type *Ty) const { for (unsigned i = 0, e = Alignments.size(); i != e; ++i) if (Alignments[i].AlignType == STACK_ALIGN) diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 24b0612..ff37542 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -34,24 +34,6 @@ using namespace llvm::dwarf; // DIDescriptor //===----------------------------------------------------------------------===// -DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) { -} - -DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) { -} - -DIDescriptor::DIDescriptor(const DILexicalBlockFile F) : DbgNode(F.DbgNode) { -} - -DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) { -} - -DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) { -} - -DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) { -} - bool DIDescriptor::Verify() const { return DbgNode && (DIDerivedType(DbgNode).Verify() || @@ -74,10 +56,8 @@ static Value *getField(const MDNode *DbgNode, unsigned Elt) { return DbgNode->getOperand(Elt); } -static const MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { - if (const MDNode *R = dyn_cast_or_null<MDNode>(getField(DbgNode, Elt))) - return R; - return 0; +static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { + return dyn_cast_or_null<MDNode>(getField(DbgNode, Elt)); } static StringRef getStringField(const MDNode *DbgNode, unsigned Elt) { @@ -115,13 +95,8 @@ int64_t DIDescriptor::getInt64Field(unsigned Elt) const { } DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { - if (DbgNode == 0) - return DIDescriptor(); - - if (Elt < DbgNode->getNumOperands()) - return - DIDescriptor(dyn_cast_or_null<const MDNode>(DbgNode->getOperand(Elt))); - return DIDescriptor(); + MDNode *Field = getNodeField(DbgNode, Elt); + return DIDescriptor(Field); } GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { @@ -167,7 +142,7 @@ unsigned DIVariable::getNumAddrElements() const { /// getInlinedAt - If this variable is inlined then return inline location. MDNode *DIVariable::getInlinedAt() const { - return dyn_cast_or_null<MDNode>(DbgNode->getOperand(7)); + return getNodeField(DbgNode, 7); } //===----------------------------------------------------------------------===// @@ -256,11 +231,6 @@ bool DIDescriptor::isGlobalVariable() const { getTag() == dwarf::DW_TAG_constant); } -/// isGlobal - Return true if the specified tag is legal for DIGlobal. -bool DIDescriptor::isGlobal() const { - return isGlobalVariable(); -} - /// isUnspecifiedParmeter - Return true if the specified tag is /// DW_TAG_unspecified_parameters. bool DIDescriptor::isUnspecifiedParameter() const { @@ -292,7 +262,9 @@ bool DIDescriptor::isTemplateTypeParameter() const { /// isTemplateValueParameter - Return true if the specified tag is /// DW_TAG_template_value_parameter. bool DIDescriptor::isTemplateValueParameter() const { - return DbgNode && getTag() == dwarf::DW_TAG_template_value_parameter; + return DbgNode && (getTag() == dwarf::DW_TAG_template_value_parameter || + getTag() == dwarf::DW_TAG_GNU_template_template_param || + getTag() == dwarf::DW_TAG_GNU_template_parameter_pack); } /// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. @@ -349,23 +321,17 @@ bool DIDescriptor::isImportedEntity() const { // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// -DIType::DIType(const MDNode *N) : DIScope(N) { - if (!N) return; - if (!isType()) - DbgNode = 0; -} - unsigned DIArray::getNumElements() const { if (!DbgNode) return 0; return DbgNode->getNumOperands(); } -/// replaceAllUsesWith - Replace all uses of debug info referenced by -/// this descriptor. +/// replaceAllUsesWith - Replace all uses of the MDNode used by this +/// type with the one in the passed descriptor. void DIType::replaceAllUsesWith(DIDescriptor &D) { - if (!DbgNode) - return; + + assert(DbgNode && "Trying to replace an unverified type!"); // Since we use a TrackingVH for the node, its easy for clients to manufacture // legitimate situations where they want to replaceAllUsesWith() on something @@ -381,11 +347,11 @@ void DIType::replaceAllUsesWith(DIDescriptor &D) { } } -/// replaceAllUsesWith - Replace all uses of debug info referenced by -/// this descriptor. +/// replaceAllUsesWith - Replace all uses of the MDNode used by this +/// type with the one in D. void DIType::replaceAllUsesWith(MDNode *D) { - if (!DbgNode) - return; + + assert(DbgNode && "Trying to replace an unverified type!"); // Since we use a TrackingVH for the node, its easy for clients to manufacture // legitimate situations where they want to replaceAllUsesWith() on something @@ -422,10 +388,12 @@ bool DIType::isUnsignedDIType() { bool DICompileUnit::Verify() const { if (!isCompileUnit()) return false; - StringRef N = getFilename(); - if (N.empty()) + + // Don't bother verifying the compilation directory or producer string + // as those could be empty. + if (getFilename().empty()) return false; - // It is possible that directory and produce string is empty. + return DbgNode->getNumOperands() == 13; } @@ -434,31 +402,54 @@ bool DIObjCProperty::Verify() const { if (!isObjCProperty()) return false; - DIType Ty = getType(); - if (!Ty.Verify()) return false; - // Don't worry about the rest of the strings for now. return DbgNode->getNumOperands() == 8; } +/// Check if a field at position Elt of a MDNode is a MDNode. +/// We currently allow an empty string and an integer. +/// But we don't allow a non-empty string in a MDNode field. +static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) { + // FIXME: This function should return true, if the field is null or the field + // is indeed a MDNode: return !Fld || isa<MDNode>(Fld). + Value *Fld = getField(DbgNode, Elt); + if (Fld && isa<MDString>(Fld) && + !cast<MDString>(Fld)->getString().empty()) + return false; + return true; +} + /// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { if (!isType()) return false; - if (getContext() && !getContext().Verify()) + // Make sure Context @ field 2 is MDNode. + if (!fieldIsMDNode(DbgNode, 2)) return false; + + // FIXME: Sink this into the various subclass verifies. unsigned Tag = getTag(); if (!isBasicType() && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type && Tag != dwarf::DW_TAG_ptr_to_member_type && Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_rvalue_reference_type && - Tag != dwarf::DW_TAG_restrict_type && - Tag != dwarf::DW_TAG_array_type && + Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_array_type && Tag != dwarf::DW_TAG_enumeration_type && Tag != dwarf::DW_TAG_subroutine_type && + Tag != dwarf::DW_TAG_inheritance && Tag != dwarf::DW_TAG_friend && getFilename().empty()) return false; + // DIType is abstract, it should be a BasicType, a DerivedType or + // a CompositeType. + if (isBasicType()) + DIBasicType(DbgNode).Verify(); + else if (isCompositeType()) + DICompositeType(DbgNode).Verify(); + else if (isDerivedType()) + DIDerivedType(DbgNode).Verify(); + else + return false; return true; } @@ -469,6 +460,14 @@ bool DIBasicType::Verify() const { /// Verify - Verify that a derived type descriptor is well formed. bool DIDerivedType::Verify() const { + // Make sure DerivedFrom @ field 9 is MDNode. + if (!fieldIsMDNode(DbgNode, 9)) + return false; + if (getTag() == dwarf::DW_TAG_ptr_to_member_type) + // Make sure ClassType @ field 10 is MDNode. + if (!fieldIsMDNode(DbgNode, 10)) + return false; + return isDerivedType() && DbgNode->getNumOperands() >= 10 && DbgNode->getNumOperands() <= 14; } @@ -477,7 +476,11 @@ bool DIDerivedType::Verify() const { bool DICompositeType::Verify() const { if (!isCompositeType()) return false; - if (getContext() && !getContext().Verify()) + + // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are MDNodes. + if (!fieldIsMDNode(DbgNode, 9)) + return false; + if (!fieldIsMDNode(DbgNode, 12)) return false; return DbgNode->getNumOperands() >= 10 && DbgNode->getNumOperands() <= 14; @@ -488,11 +491,13 @@ bool DISubprogram::Verify() const { if (!isSubprogram()) return false; - if (getContext() && !getContext().Verify()) + // Make sure context @ field 2 and type @ field 7 are MDNodes. + if (!fieldIsMDNode(DbgNode, 2)) return false; - - DICompositeType Ty = getType(); - if (!Ty.Verify()) + if (!fieldIsMDNode(DbgNode, 7)) + return false; + // Containing type @ field 12. + if (!fieldIsMDNode(DbgNode, 12)) return false; return DbgNode->getNumOperands() == 20; } @@ -504,15 +509,13 @@ bool DIGlobalVariable::Verify() const { if (getDisplayName().empty()) return false; - - if (getContext() && !getContext().Verify()) + // Make sure context @ field 2 and type @ field 8 are MDNodes. + if (!fieldIsMDNode(DbgNode, 2)) return false; - - DIType Ty = getType(); - if (!Ty.Verify()) + if (!fieldIsMDNode(DbgNode, 8)) return false; - - if (!getGlobal() && !getConstant()) + // Make sure StaticDataMemberDeclaration @ field 12 is MDNode. + if (!fieldIsMDNode(DbgNode, 12)) return false; return DbgNode->getNumOperands() == 13; @@ -523,13 +526,11 @@ bool DIVariable::Verify() const { if (!isVariable()) return false; - if (getContext() && !getContext().Verify()) + // Make sure context @ field 1 and type @ field 5 are MDNodes. + if (!fieldIsMDNode(DbgNode, 1)) return false; - - DIType Ty = getType(); - if (!Ty.Verify()) + if (!fieldIsMDNode(DbgNode, 5)) return false; - return DbgNode->getNumOperands() >= 8; } @@ -550,7 +551,7 @@ bool DINameSpace::Verify() const { /// \brief Retrieve the MDNode for the directory/file pair. MDNode *DIFile::getFileNode() const { - return const_cast<MDNode*>(getNodeField(DbgNode, 1)); + return getNodeField(DbgNode, 1); } /// \brief Verify that the file descriptor is well formed. @@ -625,9 +626,7 @@ uint64_t DIDerivedType::getOriginalTypeSize() const { /// getObjCProperty - Return property node, if this ivar is associated with one. MDNode *DIDerivedType::getObjCProperty() const { - if (DbgNode->getNumOperands() <= 10) - return NULL; - return dyn_cast_or_null<MDNode>(DbgNode->getOperand(10)); + return getNodeField(DbgNode, 10); } /// \brief Set the array of member DITypes. @@ -682,28 +681,38 @@ unsigned DISubprogram::isOptimized() const { } MDNode *DISubprogram::getVariablesNodes() const { - if (!DbgNode || DbgNode->getNumOperands() <= 18) - return NULL; - return dyn_cast_or_null<MDNode>(DbgNode->getOperand(18)); + return getNodeField(DbgNode, 18); } DIArray DISubprogram::getVariables() const { - if (!DbgNode || DbgNode->getNumOperands() <= 18) - return DIArray(); - if (MDNode *T = dyn_cast_or_null<MDNode>(DbgNode->getOperand(18))) - return DIArray(T); - return DIArray(); + return DIArray(getNodeField(DbgNode, 18)); } Value *DITemplateValueParameter::getValue() const { return getField(DbgNode, 4); } -void DIScope::setFilename(StringRef Name, LLVMContext &Context) { - if (!DbgNode) - return; - MDString *MDName(MDString::get(Context, Name)); - const_cast<MDNode*>(getNodeField(DbgNode, 1))->replaceOperandWith(0, MDName); +// If the current node has a parent scope then return that, +// else return an empty scope. +DIScope DIScope::getContext() const { + + if (isType()) + return DIType(DbgNode).getContext(); + + if (isSubprogram()) + return DISubprogram(DbgNode).getContext(); + + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getContext(); + + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getContext(); + + if (isNameSpace()) + return DINameSpace(DbgNode).getContext(); + + assert((isFile() || isCompileUnit()) && "Unhandled type of scope."); + return DIScope(); } StringRef DIScope::getFilename() const { @@ -722,27 +731,21 @@ DIArray DICompileUnit::getEnumTypes() const { if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); - if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(7))) - return DIArray(N); - return DIArray(); + return DIArray(getNodeField(DbgNode, 7)); } DIArray DICompileUnit::getRetainedTypes() const { if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); - if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(8))) - return DIArray(N); - return DIArray(); + return DIArray(getNodeField(DbgNode, 8)); } DIArray DICompileUnit::getSubprograms() const { if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); - if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(9))) - return DIArray(N); - return DIArray(); + return DIArray(getNodeField(DbgNode, 9)); } @@ -750,18 +753,14 @@ DIArray DICompileUnit::getGlobalVariables() const { if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); - if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(10))) - return DIArray(N); - return DIArray(); + return DIArray(getNodeField(DbgNode, 10)); } DIArray DICompileUnit::getImportedEntities() const { if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); - if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(11))) - return DIArray(N); - return DIArray(); + return DIArray(getNodeField(DbgNode, 11)); } /// fixupSubprogramName - Replace contains special characters used @@ -873,6 +872,15 @@ bool llvm::isSubprogramContext(const MDNode *Context) { // DebugInfoFinder implementations. //===----------------------------------------------------------------------===// +void DebugInfoFinder::reset() { + CUs.clear(); + SPs.clear(); + GVs.clear(); + TYs.clear(); + Scopes.clear(); + NodesSeen.clear(); +} + /// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(const Module &M) { if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { @@ -882,8 +890,10 @@ void DebugInfoFinder::processModule(const Module &M) { DIArray GVs = CU.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { DIGlobalVariable DIG(GVs.getElement(i)); - if (addGlobalVariable(DIG)) + if (addGlobalVariable(DIG)) { + processScope(DIG.getContext()); processType(DIG.getType()); + } } DIArray SPs = CU.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) @@ -902,18 +912,8 @@ void DebugInfoFinder::processModule(const Module &M) { /// processLocation - Process DILocation. void DebugInfoFinder::processLocation(DILocation Loc) { - if (!Loc.Verify()) return; - DIDescriptor S(Loc.getScope()); - if (S.isCompileUnit()) - addCompileUnit(DICompileUnit(S)); - else if (S.isSubprogram()) - processSubprogram(DISubprogram(S)); - else if (S.isLexicalBlock()) - processLexicalBlock(DILexicalBlock(S)); - else if (S.isLexicalBlockFile()) { - DILexicalBlockFile DBF = DILexicalBlockFile(S); - processLexicalBlock(DILexicalBlock(DBF.getScope())); - } + if (!Loc) return; + processScope(Loc.getScope()); processLocation(Loc.getOrigLocation()); } @@ -921,6 +921,7 @@ void DebugInfoFinder::processLocation(DILocation Loc) { void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; + processScope(DT.getContext()); if (DT.isCompositeType()) { DICompositeType DCT(DT); processType(DCT.getTypeDerivedFrom()); @@ -938,6 +939,34 @@ void DebugInfoFinder::processType(DIType DT) { } } +void DebugInfoFinder::processScope(DIScope Scope) { + if (Scope.isType()) { + DIType Ty(Scope); + processType(Ty); + return; + } + if (Scope.isCompileUnit()) { + addCompileUnit(DICompileUnit(Scope)); + return; + } + if (Scope.isSubprogram()) { + processSubprogram(DISubprogram(Scope)); + return; + } + if (!addScope(Scope)) + return; + if (Scope.isLexicalBlock()) { + DILexicalBlock LB(Scope); + processScope(LB.getContext()); + } else if (Scope.isLexicalBlockFile()) { + DILexicalBlockFile LBF = DILexicalBlockFile(Scope); + processScope(LBF.getScope()); + } else if (Scope.isNameSpace()) { + DINameSpace NS(Scope); + processScope(NS.getContext()); + } +} + /// processLexicalBlock void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { DIScope Context = LB.getContext(); @@ -955,6 +984,7 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { void DebugInfoFinder::processSubprogram(DISubprogram SP) { if (!addSubprogram(SP)) return; + processScope(SP.getContext()); processType(SP.getType()); } @@ -969,12 +999,27 @@ void DebugInfoFinder::processDeclare(const DbgDeclareInst *DDI) { if (!NodesSeen.insert(DV)) return; + processScope(DIVariable(N).getContext()); + processType(DIVariable(N).getType()); +} + +void DebugInfoFinder::processValue(const DbgValueInst *DVI) { + MDNode *N = dyn_cast<MDNode>(DVI->getVariable()); + if (!N) return; + + DIDescriptor DV(N); + if (!DV.isVariable()) + return; + + if (!NodesSeen.insert(DV)) + return; + processScope(DIVariable(N).getContext()); processType(DIVariable(N).getType()); } /// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { - if (!DT.isValid()) + if (!DT) return false; if (!NodesSeen.insert(DT)) @@ -986,9 +1031,8 @@ bool DebugInfoFinder::addType(DIType DT) { /// addCompileUnit - Add compile unit into CUs. bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { - if (!CU.Verify()) + if (!CU) return false; - if (!NodesSeen.insert(CU)) return false; @@ -998,7 +1042,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { /// addGlobalVariable - Add global variable into GVs. bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { - if (!DIDescriptor(DIG).isGlobalVariable()) + if (!DIG) return false; if (!NodesSeen.insert(DIG)) @@ -1010,7 +1054,7 @@ bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { // addSubprogram - Add subprgoram into SPs. bool DebugInfoFinder::addSubprogram(DISubprogram SP) { - if (!DIDescriptor(SP).isSubprogram()) + if (!SP) return false; if (!NodesSeen.insert(SP)) @@ -1020,6 +1064,19 @@ bool DebugInfoFinder::addSubprogram(DISubprogram SP) { return true; } +bool DebugInfoFinder::addScope(DIScope Scope) { + if (!Scope) + return false; + // FIXME: Ocaml binding generates a scope with no content, we treat it + // as null for now. + if (Scope->getNumOperands() == 0) + return false; + if (!NodesSeen.insert(Scope)) + return false; + Scopes.push_back(Scope); + return true; +} + //===----------------------------------------------------------------------===// // DIDescriptor: dump routines for all descriptors. //===----------------------------------------------------------------------===// @@ -1120,7 +1177,12 @@ void DIType::printInternal(raw_ostream &OS) const { OS << " [artificial]"; if (isForwardDecl()) - OS << " [fwd]"; + OS << " [decl]"; + else if (getTag() == dwarf::DW_TAG_structure_type || + getTag() == dwarf::DW_TAG_union_type || + getTag() == dwarf::DW_TAG_enumeration_type || + getTag() == dwarf::DW_TAG_class_type) + OS << " [def]"; if (isVector()) OS << " [vector]"; if (isStaticMember()) @@ -1206,11 +1268,10 @@ static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, const LLVMContext &Ctx) { if (!DL.isUnknown()) { // Print source line info. DIScope Scope(DL.getScope(Ctx)); + assert(Scope.isScope() && + "Scope of a DebugLoc should be a DIScope."); // Omit the directory, because it's likely to be long and uninteresting. - if (Scope.Verify()) - CommentOS << Scope.getFilename(); - else - CommentOS << "<unknown>"; + CommentOS << Scope.getFilename(); CommentOS << ':' << DL.getLine(); if (DL.getCol() != 0) CommentOS << ':' << DL.getCol(); diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 7f7efabf..bf9d949 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -131,6 +131,15 @@ bool Argument::hasReturnedAttr() const { hasAttribute(getArgNo()+1, Attribute::Returned); } +/// Return true if this argument has the readonly or readnone attribute on it +/// in its containing function. +bool Argument::onlyReadsMemory() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::ReadOnly) || + getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::ReadNone); +} + /// addAttr - Add attributes to an argument. void Argument::addAttr(AttributeSet AS) { assert(AS.getNumSlots() <= 1 && @@ -711,4 +720,3 @@ bool Function::callsFunctionThatReturnsTwice() const { return false; } - diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp index ea2f0a6..e9baa5c 100644 --- a/lib/IR/GCOV.cpp +++ b/lib/IR/GCOV.cpp @@ -63,7 +63,7 @@ bool GCOVFile::read(GCOVBuffer &Buffer) { /// dump - Dump GCOVFile content on standard out for debugging purposes. void GCOVFile::dump() { - for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(), + for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(), E = Functions.end(); I != E; ++I) (*I)->dump(); } @@ -71,7 +71,7 @@ void GCOVFile::dump() { /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVFile::collectLineCounts(FileInfo &FI) { - for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(), + for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(), E = Functions.end(); I != E; ++I) (*I)->collectLineCounts(FI); FI.print(); @@ -94,7 +94,7 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) { Buff.readInt(); // Function header length Ident = Buff.readInt(); Buff.readInt(); // Checksum #1 - if (Format != GCOV::GCNO_402) + if (Format != GCOV::GCNO_402 && Format != GCOV::GCDA_402) Buff.readInt(); // Checksum #2 Name = Buff.readString(); @@ -155,7 +155,7 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) { /// dump - Dump GCOVFunction content on standard out for debugging purposes. void GCOVFunction::dump() { outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n"; - for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(), + for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(), E = Blocks.end(); I != E; ++I) (*I)->dump(); } @@ -163,7 +163,7 @@ void GCOVFunction::dump() { /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVFunction::collectLineCounts(FileInfo &FI) { - for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(), + for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(), E = Blocks.end(); I != E; ++I) (*I)->collectLineCounts(FI); } @@ -197,7 +197,7 @@ void GCOVBlock::dump() { outs() << "Block : " << Number << " Counter : " << Counter << "\n"; if (!Edges.empty()) { outs() << "\tEdges : "; - for (SmallVector<uint32_t, 16>::iterator I = Edges.begin(), E = Edges.end(); + for (SmallVectorImpl<uint32_t>::iterator I = Edges.begin(), E = Edges.end(); I != E; ++I) outs() << (*I) << ","; outs() << "\n"; @@ -220,14 +220,14 @@ void GCOVBlock::dump() { /// reading .gcno and .gcda files. void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count) { - for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(), + for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(), E = Lines.end(); I != E; ++I) FI.addLineCount(Filename, *I, Count); } /// dump - Dump GCOVLines content on standard out for debugging purposes. void GCOVLines::dump() { - for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(), + for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(), E = Lines.end(); I != E; ++I) outs() << (*I) << ","; } diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index d58877e..205cb43 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -346,7 +346,7 @@ void CallInst::removeAttribute(unsigned i, Attribute attr) { setAttributes(PAL); } -bool CallInst::hasFnAttr(Attribute::AttrKind A) const { +bool CallInst::hasFnAttrImpl(Attribute::AttrKind A) const { if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) return true; if (const Function *F = getCalledFunction()) @@ -574,7 +574,7 @@ void InvokeInst::setSuccessorV(unsigned idx, BasicBlock *B) { return setSuccessor(idx, B); } -bool InvokeInst::hasFnAttr(Attribute::AttrKind A) const { +bool InvokeInst::hasFnAttrImpl(Attribute::AttrKind A) const { if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) return true; if (const Function *F = getCalledFunction()) @@ -2224,12 +2224,20 @@ unsigned CastInst::isEliminableCastPair( if (SrcTy->isFloatingPointTy()) return secondOp; return 0; - case 7: { - // ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size + case 7: { + unsigned MidSize = MidTy->getScalarSizeInBits(); + // Check the address spaces first. If we know they are in the same address + // space, the pointer sizes must be the same so we can still fold this + // without knowing the actual sizes as long we know that the intermediate + // pointer is the largest possible pointer size. + if (MidSize == 64 && + SrcTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace()) + return Instruction::BitCast; + + // ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size. if (!SrcIntPtrTy || DstIntPtrTy != SrcIntPtrTy) return 0; unsigned PtrSize = SrcIntPtrTy->getScalarSizeInBits(); - unsigned MidSize = MidTy->getScalarSizeInBits(); if (MidSize >= PtrSize) return Instruction::BitCast; return 0; @@ -2254,17 +2262,46 @@ unsigned CastInst::isEliminableCastPair( if (SrcTy == DstTy) return Instruction::BitCast; return 0; // If the types are not the same we can't eliminate it. - case 11: - // bitcast followed by ptrtoint is allowed as long as the bitcast - // is a pointer to pointer cast. - if (SrcTy->isPointerTy() && MidTy->isPointerTy()) + case 11: { + // bitcast followed by ptrtoint is allowed as long as the bitcast is a + // pointer to pointer cast, and the pointers are the same size. + PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy); + PointerType *MidPtrTy = dyn_cast<PointerType>(MidTy); + if (!SrcPtrTy || !MidPtrTy) + return 0; + + // If the address spaces are the same, we know they are the same size + // without size information + if (SrcPtrTy->getAddressSpace() == MidPtrTy->getAddressSpace()) return secondOp; + + if (!SrcIntPtrTy || !MidIntPtrTy) + return 0; + + if (SrcIntPtrTy->getScalarSizeInBits() == + MidIntPtrTy->getScalarSizeInBits()) + return secondOp; + return 0; - case 12: - // inttoptr, bitcast -> intptr if bitcast is a ptr to ptr cast - if (MidTy->isPointerTy() && DstTy->isPointerTy()) + } + case 12: { + // inttoptr, bitcast -> inttoptr if bitcast is a ptr to ptr cast + // and the ptrs are to address spaces of the same size + PointerType *MidPtrTy = dyn_cast<PointerType>(MidTy); + PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy); + if (!MidPtrTy || !DstPtrTy) + return 0; + + if (MidPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace()) + return firstOp; + + if (MidIntPtrTy && + DstIntPtrTy && + MidIntPtrTy->getScalarSizeInBits() == + DstIntPtrTy->getScalarSizeInBits()) return firstOp; return 0; + } case 13: { // inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize if (!MidIntPtrTy) @@ -2378,22 +2415,30 @@ CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty, CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd) { - assert(S->getType()->isPointerTy() && "Invalid cast"); - assert((Ty->isIntegerTy() || Ty->isPointerTy()) && + assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"); + assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) && + "Invalid cast"); + assert(Ty->isVectorTy() == S->getType()->isVectorTy() && "Invalid cast"); + assert((!Ty->isVectorTy() || + Ty->getVectorNumElements() == S->getType()->getVectorNumElements()) && "Invalid cast"); - if (Ty->isIntegerTy()) + if (Ty->isIntOrIntVectorTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd); return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd); } /// @brief Create a BitCast or a PtrToInt cast instruction -CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, - const Twine &Name, +CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, + const Twine &Name, Instruction *InsertBefore) { assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"); assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) && "Invalid cast"); + assert(Ty->isVectorTy() == S->getType()->isVectorTy() && "Invalid cast"); + assert((!Ty->isVectorTy() || + Ty->getVectorNumElements() == S->getType()->getVectorNumElements()) && + "Invalid cast"); if (Ty->isIntOrIntVectorTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore); @@ -2517,8 +2562,48 @@ bool CastInst::isCastable(Type *SrcTy, Type *DestTy) { } } -// Provide a way to get a "cast" where the cast opcode is inferred from the -// types and size of the operand. This, basically, is a parallel of the +bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) { + if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType()) + return false; + + if (SrcTy == DestTy) + return true; + + if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) { + if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy)) { + if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) { + // An element by element cast. Valid if casting the elements is valid. + SrcTy = SrcVecTy->getElementType(); + DestTy = DestVecTy->getElementType(); + } + } + } + + if (PointerType *DestPtrTy = dyn_cast<PointerType>(DestTy)) { + if (PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy)) { + return SrcPtrTy->getAddressSpace() == DestPtrTy->getAddressSpace(); + } + } + + unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr + unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr + + // Could still have vectors of pointers if the number of elements doesn't + // match + if (SrcBits == 0 || DestBits == 0) + return false; + + if (SrcBits != DestBits) + return false; + + if (DestTy->isX86_MMXTy() || SrcTy->isX86_MMXTy()) + return false; + + return true; +} + +// Provide a way to get a "cast" where the cast opcode is inferred from the +// types and size of the operand. This, basically, is a parallel of the // logic in the castIsValid function below. This axiom should hold: // castIsValid( getCastOpcode(Val, Ty), Val, Ty) // should not assert in castIsValid. In other words, this produces a "correct" @@ -2535,6 +2620,7 @@ CastInst::getCastOpcode( if (SrcTy == DestTy) return BitCast; + // FIXME: Check address space sizes here if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy)) if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) { @@ -2601,6 +2687,7 @@ CastInst::getCastOpcode( return BitCast; } else if (DestTy->isPointerTy()) { if (SrcTy->isPointerTy()) { + // TODO: Address space pointer sizes may not match return BitCast; // ptr -> ptr } else if (SrcTy->isIntegerTy()) { return IntToPtr; // int -> ptr diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 6a6b7af5..bd4d9c0 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -422,7 +422,7 @@ static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) { return !A.intersectWith(B).isEmptySet() || isContiguous(A, B); } -static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low, +static bool tryMergeRange(SmallVectorImpl<Value *> &EndPoints, ConstantInt *Low, ConstantInt *High) { ConstantRange NewRange(Low->getValue(), High->getValue()); unsigned Size = EndPoints.size(); @@ -439,7 +439,7 @@ static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low, return false; } -static void addRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low, +static void addRange(SmallVectorImpl<Value *> &EndPoints, ConstantInt *Low, ConstantInt *High) { if (!EndPoints.empty()) if (tryMergeRange(EndPoints, Low, High)) diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index 3f505aa..968b8f4 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -233,8 +233,7 @@ Function *Module::getFunction(StringRef Name) const { /// If AllowLocal is set to true, this function will return types that /// have an local. By default, these types are not returned. /// -GlobalVariable *Module::getGlobalVariable(StringRef Name, - bool AllowLocal) const { +GlobalVariable *Module::getGlobalVariable(StringRef Name, bool AllowLocal) { if (GlobalVariable *Result = dyn_cast_or_null<GlobalVariable>(getNamedValue(Name))) if (AllowLocal || !Result->hasLocalLinkage()) @@ -325,6 +324,19 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { } } +/// Return the corresponding value if Key appears in module flags, otherwise +/// return null. +Value *Module::getModuleFlag(StringRef Key) const { + SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; + getModuleFlagsMetadata(ModuleFlags); + for (unsigned I = 0, E = ModuleFlags.size(); I < E; ++I) { + const ModuleFlagEntry &MFE = ModuleFlags[I]; + if (Key == MFE.Key->getString()) + return MFE.Val; + } + return 0; +} + /// getModuleFlagsMetadata - Returns the NamedMDNode in the module that /// represents module-level flags. This method returns null if there are no /// module-level flags. diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 387094a..ee53c85 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -704,7 +704,7 @@ Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) { // Check the immutable passes. Iterate in reverse order so that we find // the most recently registered passes first. - for (SmallVector<ImmutablePass *, 8>::reverse_iterator I = + for (SmallVectorImpl<ImmutablePass *>::reverse_iterator I = ImmutablePasses.rbegin(), E = ImmutablePasses.rend(); I != E; ++I) { AnalysisID PI = (*I)->getPassID(); if (PI == AID) @@ -741,8 +741,8 @@ void PMTopLevelManager::dumpPasses() const { // (sometimes indirectly), but there's no inheritance relationship // between PMDataManager and Pass, so we have to getAsPass to get // from a PMDataManager* to a Pass*. - for (SmallVector<PMDataManager *, 8>::const_iterator I = PassManagers.begin(), - E = PassManagers.end(); I != E; ++I) + for (SmallVectorImpl<PMDataManager *>::const_iterator I = + PassManagers.begin(), E = PassManagers.end(); I != E; ++I) (*I)->getAsPass()->dumpPassStructure(1); } @@ -752,7 +752,7 @@ void PMTopLevelManager::dumpArguments() const { return; dbgs() << "Pass Arguments: "; - for (SmallVector<ImmutablePass *, 8>::const_iterator I = + for (SmallVectorImpl<ImmutablePass *>::const_iterator I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I) if (const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID())) { @@ -760,8 +760,8 @@ void PMTopLevelManager::dumpArguments() const { if (!PI->isAnalysisGroup()) dbgs() << " -" << PI->getPassArgument(); } - for (SmallVector<PMDataManager *, 8>::const_iterator I = PassManagers.begin(), - E = PassManagers.end(); I != E; ++I) + for (SmallVectorImpl<PMDataManager *>::const_iterator I = + PassManagers.begin(), E = PassManagers.end(); I != E; ++I) (*I)->dumpPassArguments(); dbgs() << "\n"; } diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp index a0b64ed..d3b2f1f 100644 --- a/lib/IR/PassRegistry.cpp +++ b/lib/IR/PassRegistry.cpp @@ -21,6 +21,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/RWMutex.h" #include <vector> using namespace llvm; @@ -35,7 +36,7 @@ PassRegistry *PassRegistry::getPassRegistry() { return &*PassRegistryObj; } -static ManagedStatic<sys::SmartMutex<true> > Lock; +static ManagedStatic<sys::SmartRWMutex<true> > Lock; //===----------------------------------------------------------------------===// // PassRegistryImpl @@ -72,7 +73,7 @@ void *PassRegistry::getImpl() const { // PassRegistry::~PassRegistry() { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(pImpl); for (std::vector<const PassInfo*>::iterator I = Impl->ToFree.begin(), @@ -84,14 +85,14 @@ PassRegistry::~PassRegistry() { } const PassInfo *PassRegistry::getPassInfo(const void *TI) const { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedReader<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI); return I != Impl->PassInfoMap.end() ? I->second : 0; } const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedReader<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); PassRegistryImpl::StringMapType::const_iterator I = Impl->PassInfoStringMap.find(Arg); @@ -103,7 +104,7 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { // void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); bool Inserted = Impl->PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; @@ -120,7 +121,7 @@ void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { } void PassRegistry::unregisterPass(const PassInfo &PI) { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); PassRegistryImpl::MapType::iterator I = Impl->PassInfoMap.find(PI.getTypeInfo()); @@ -132,7 +133,7 @@ void PassRegistry::unregisterPass(const PassInfo &PI) { } void PassRegistry::enumerateWith(PassRegistrationListener *L) { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedReader<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); for (PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.begin(), E = Impl->PassInfoMap.end(); I != E; ++I) @@ -160,7 +161,7 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID, assert(ImplementationInfo && "Must register pass before adding to AnalysisGroup!"); - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(*Lock); // Make sure we keep track of the fact that the implementation implements // the interface. @@ -186,13 +187,13 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID, } void PassRegistry::addRegistrationListener(PassRegistrationListener *L) { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(*Lock); PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); Impl->Listeners.push_back(L); } void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) { - sys::SmartScopedLock<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(*Lock); // NOTE: This is necessary, because removeRegistrationListener() can be called // as part of the llvm_shutdown sequence. Since we have no control over the diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index f8774bc..0eda97f 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -53,8 +53,10 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Assembly/Writer.h" +#include "llvm/DebugInfo.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" @@ -66,6 +68,7 @@ #include "llvm/PassManager.h" #include "llvm/Support/CFG.h" #include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -74,6 +77,9 @@ #include <cstdarg> using namespace llvm; +static cl::opt<bool> DisableDebugInfoVerifier("disable-debug-info-verifier", + cl::init(false)); + namespace { // Anonymous namespace for class struct PreVerifier : public FunctionPass { static char ID; // Pass ID, replacement for typeid @@ -93,7 +99,7 @@ namespace { // Anonymous namespace for class for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { if (I->empty() || !I->back().isTerminator()) { - dbgs() << "Basic Block in function '" << F.getName() + dbgs() << "Basic Block in function '" << F.getName() << "' does not have terminator!\n"; WriteAsOperand(dbgs(), I, true); dbgs() << "\n"; @@ -110,7 +116,7 @@ namespace { // Anonymous namespace for class } char PreVerifier::ID = 0; -INITIALIZE_PASS(PreVerifier, "preverify", "Preliminary module verification", +INITIALIZE_PASS(PreVerifier, "preverify", "Preliminary module verification", false, false) static char &PreVerifyID = PreVerifier::ID; @@ -123,6 +129,7 @@ namespace { Module *Mod; // Module we are verifying right now LLVMContext *Context; // Context within which we are verifying DominatorTree *DT; // Dominator Tree, caution can be null! + const DataLayout *DL; std::string Messages; raw_string_ostream MessagesStr; @@ -142,21 +149,27 @@ namespace { /// the same personality function. const Value *PersonalityFn; + /// Finder keeps track of all debug info MDNodes in a Module. + DebugInfoFinder Finder; + Verifier() : FunctionPass(ID), Broken(false), - action(AbortProcessAction), Mod(0), Context(0), DT(0), + action(AbortProcessAction), Mod(0), Context(0), DT(0), DL(0), MessagesStr(Messages), PersonalityFn(0) { initializeVerifierPass(*PassRegistry::getPassRegistry()); } explicit Verifier(VerifierFailureAction ctn) : FunctionPass(ID), Broken(false), action(ctn), Mod(0), - Context(0), DT(0), MessagesStr(Messages), PersonalityFn(0) { + Context(0), DT(0), DL(0), MessagesStr(Messages), PersonalityFn(0) { initializeVerifierPass(*PassRegistry::getPassRegistry()); } bool doInitialization(Module &M) { Mod = &M; Context = &M.getContext(); + Finder.reset(); + + DL = getAnalysisIfAvailable<DataLayout>(); // We must abort before returning back to the pass manager, or else the // pass manager may try to run other passes on the broken module. @@ -188,11 +201,11 @@ namespace { if (I->isDeclaration()) visitFunction(*I); } - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) visitGlobalVariable(*I); - for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) visitGlobalAlias(*I); @@ -202,6 +215,9 @@ namespace { visitModuleFlags(M); + // Verify Debug Info. + verifyDebugInfo(M); + // If the module is broken, abort at this time. return abortIfBroken(); } @@ -309,6 +325,11 @@ namespace { void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V); + void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy); + void VerifyConstantExprBitcastType(const ConstantExpr *CE); + + void verifyDebugInfo(Module &M); + void WriteValue(const Value *V) { if (!V) return; if (isa<Instruction>(V)) { @@ -450,7 +471,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { } if (GV.hasName() && (GV.getName() == "llvm.used" || - GV.getName() == "llvm.compiler_used")) { + GV.getName() == "llvm.compiler.used")) { Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(), "invalid linkage for intrinsic global variable", &GV); Type *GVType = GV.getType()->getElementType(); @@ -473,6 +494,33 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { } } + if (!GV.hasInitializer()) { + visitGlobalValue(GV); + return; + } + + // Walk any aggregate initializers looking for bitcasts between address spaces + SmallPtrSet<const Value *, 4> Visited; + SmallVector<const Value *, 4> WorkStack; + WorkStack.push_back(cast<Value>(GV.getInitializer())); + + while (!WorkStack.empty()) { + const Value *V = WorkStack.pop_back_val(); + if (!Visited.insert(V)) + continue; + + if (const User *U = dyn_cast<User>(V)) { + for (unsigned I = 0, N = U->getNumOperands(); I != N; ++I) + WorkStack.push_back(U->getOperand(I)); + } + + if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { + VerifyConstantExprBitcastType(CE); + if (Broken) + return; + } + } + visitGlobalValue(GV); } @@ -488,18 +536,29 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) { "Alias and aliasee types should match!", &GA); Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA); - if (!isa<GlobalValue>(GA.getAliasee())) { - const ConstantExpr *CE = dyn_cast<ConstantExpr>(GA.getAliasee()); - Assert1(CE && + Constant *Aliasee = GA.getAliasee(); + + if (!isa<GlobalValue>(Aliasee)) { + ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee); + Assert1(CE && (CE->getOpcode() == Instruction::BitCast || CE->getOpcode() == Instruction::GetElementPtr) && isa<GlobalValue>(CE->getOperand(0)), "Aliasee should be either GlobalValue or bitcast of GlobalValue", &GA); + + if (CE->getOpcode() == Instruction::BitCast) { + unsigned SrcAS = CE->getOperand(0)->getType()->getPointerAddressSpace(); + unsigned DstAS = CE->getType()->getPointerAddressSpace(); + + Assert1(SrcAS == DstAS, + "Alias bitcasts cannot be between different address spaces", + &GA); + } } - const GlobalValue* Aliasee = GA.resolveAliasedGlobal(/*stopOnWeak*/ false); - Assert1(Aliasee, + const GlobalValue* Resolved = GA.resolveAliasedGlobal(/*stopOnWeak*/ false); + Assert1(Resolved, "Aliasing chain should end with function or global variable", &GA); visitGlobalValue(GA); @@ -654,7 +713,7 @@ void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs, } void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, - bool isFunction, const Value* V) { + bool isFunction, const Value *V) { unsigned Slot = ~0U; for (unsigned I = 0, E = Attrs.getNumSlots(); I != E; ++I) if (Attrs.getSlotIndex(I) == Idx) { @@ -671,8 +730,6 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, if (I->getKindAsEnum() == Attribute::NoReturn || I->getKindAsEnum() == Attribute::NoUnwind || - I->getKindAsEnum() == Attribute::ReadNone || - I->getKindAsEnum() == Attribute::ReadOnly || I->getKindAsEnum() == Attribute::NoInline || I->getKindAsEnum() == Attribute::AlwaysInline || I->getKindAsEnum() == Attribute::OptimizeForSize || @@ -692,16 +749,25 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, I->getKindAsEnum() == Attribute::SanitizeMemory || I->getKindAsEnum() == Attribute::MinSize || I->getKindAsEnum() == Attribute::NoDuplicate || + I->getKindAsEnum() == Attribute::Builtin || I->getKindAsEnum() == Attribute::NoBuiltin || I->getKindAsEnum() == Attribute::Cold) { - if (!isFunction) - CheckFailed("Attribute '" + I->getKindAsString() + - "' only applies to functions!", V); - return; - } else if (isFunction) { - CheckFailed("Attribute '" + I->getKindAsString() + - "' does not apply to functions!", V); + if (!isFunction) { + CheckFailed("Attribute '" + I->getAsString() + + "' only applies to functions!", V); return; + } + } else if (I->getKindAsEnum() == Attribute::ReadOnly || + I->getKindAsEnum() == Attribute::ReadNone) { + if (Idx == 0) { + CheckFailed("Attribute '" + I->getAsString() + + "' does not apply to function returns"); + return; + } + } else if (isFunction) { + CheckFailed("Attribute '" + I->getAsString() + + "' does not apply to functions!", V); + return; } } } @@ -833,6 +899,52 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, "Attributes 'noinline and alwaysinline' are incompatible!", V); } +void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) { + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + // BitCast implies a no-op cast of type only. No bits change. + // However, you can't cast pointers to anything but pointers. + Assert1(SrcTy->isPointerTy() == DestTy->isPointerTy(), + "Bitcast requires both operands to be pointer or neither", V); + Assert1(SrcBitSize == DestBitSize, + "Bitcast requires types of same width", V); + + // Disallow aggregates. + Assert1(!SrcTy->isAggregateType(), + "Bitcast operand must not be aggregate", V); + Assert1(!DestTy->isAggregateType(), + "Bitcast type must not be aggregate", V); + + // Without datalayout, assume all address spaces are the same size. + // Don't check if both types are not pointers. + // Skip casts between scalars and vectors. + if (!DL || + !SrcTy->isPtrOrPtrVectorTy() || + !DestTy->isPtrOrPtrVectorTy() || + SrcTy->isVectorTy() != DestTy->isVectorTy()) { + return; + } + + unsigned SrcAS = SrcTy->getPointerAddressSpace(); + unsigned DstAS = DestTy->getPointerAddressSpace(); + + unsigned SrcASSize = DL->getPointerSizeInBits(SrcAS); + unsigned DstASSize = DL->getPointerSizeInBits(DstAS); + Assert1(SrcASSize == DstASSize, + "Bitcasts between pointers of different address spaces must have " + "the same size pointers, otherwise use PtrToInt/IntToPtr.", V); +} + +void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) { + if (CE->getOpcode() == Instruction::BitCast) { + Type *SrcTy = CE->getOperand(0)->getType(); + Type *DstTy = CE->getType(); + VerifyBitcastType(CE, DstTy, SrcTy); + } +} + bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { if (Attrs.getNumSlots() == 0) return true; @@ -843,7 +955,7 @@ bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { || (LastIndex == AttributeSet::FunctionIndex && (LastSlot == 0 || Attrs.getSlotIndex(LastSlot - 1) <= Params))) return true; - + return false; } @@ -862,7 +974,7 @@ void Verifier::visitFunction(Function &F) { "# formal arguments must match # of arguments for function type!", &F, FT); Assert1(F.getReturnType()->isFirstClassType() || - F.getReturnType()->isVoidTy() || + F.getReturnType()->isVoidTy() || F.getReturnType()->isStructTy(), "Functions cannot return aggregate values!", &F); @@ -877,6 +989,13 @@ void Verifier::visitFunction(Function &F) { // Check function attributes. VerifyFunctionAttrs(FT, Attrs, &F); + // On function declarations/definitions, we do not support the builtin + // attribute. We do not check this in VerifyFunctionAttrs since that is + // checking for Attributes that can/can not ever be on functions. + Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::Builtin), + "Attribute 'builtin' can only be applied to a callsite.", &F); + // Check that this function meets the restrictions on this calling convention. switch (F.getCallingConv()) { default: @@ -922,25 +1041,25 @@ void Verifier::visitFunction(Function &F) { // Verify that this function (which has a body) is not named "llvm.*". It // is not legal to define intrinsics. Assert1(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F); - + // Check the entry node BasicBlock *Entry = &F.getEntryBlock(); Assert1(pred_begin(Entry) == pred_end(Entry), "Entry block to function must not have predecessors!", Entry); - + // The address of the entry block cannot be taken, unless it is dead. if (Entry->hasAddressTaken()) { Assert1(!BlockAddress::get(Entry)->isConstantUsed(), "blockaddress may not be used with the entry block!", Entry); } } - + // If this function is actually an intrinsic, verify that it is only used in // direct call/invokes, never having its "address taken". if (F.getIntrinsicID()) { const User *U; if (F.hasAddressTaken(&U)) - Assert1(0, "Invalid user of intrinsic instruction!", U); + Assert1(0, "Invalid user of intrinsic instruction!", U); } } @@ -1015,7 +1134,7 @@ void Verifier::visitBranchInst(BranchInst &BI) { void Verifier::visitReturnInst(ReturnInst &RI) { Function *F = RI.getParent()->getParent(); unsigned N = RI.getNumOperands(); - if (F->getReturnType()->isVoidTy()) + if (F->getReturnType()->isVoidTy()) Assert2(N == 0, "Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); @@ -1048,14 +1167,14 @@ void Verifier::visitSwitchInst(SwitchInst &SI) { RangeSetMap[r] = i.getCaseIndex(); } } - + IntegersSubsetToBB::RangeIterator errItem; if (!Mapping.verify(errItem)) { unsigned CaseIndex = RangeSetMap[errItem->first]; SwitchInst::CaseIt i(&SI, CaseIndex); Assert2(false, "Duplicate integer as switch case", &SI, i.getCaseValueEx()); } - + visitTerminatorInst(SI); } @@ -1310,26 +1429,9 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) { } void Verifier::visitBitCastInst(BitCastInst &I) { - // Get the source and destination types Type *SrcTy = I.getOperand(0)->getType(); Type *DestTy = I.getType(); - - // Get the size of the types in bits, we'll need this later - unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); - unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); - - // BitCast implies a no-op cast of type only. No bits change. - // However, you can't cast pointers to anything but pointers. - Assert1(SrcTy->isPointerTy() == DestTy->isPointerTy(), - "Bitcast requires both operands to be pointer or neither", &I); - Assert1(SrcBitSize == DestBitSize, "Bitcast requires types of same width",&I); - - // Disallow aggregates. - Assert1(!SrcTy->isAggregateType(), - "Bitcast operand must not be aggregate", &I); - Assert1(!DestTy->isAggregateType(), - "Bitcast type must not be aggregate", &I); - + VerifyBitcastType(&I, DestTy, SrcTy); visitInstruction(I); } @@ -1340,7 +1442,7 @@ void Verifier::visitPHINode(PHINode &PN) { // This can be tested by checking whether the instruction before this is // either nonexistent (because this is begin()) or is a PHI node. If not, // then there is some other instruction before a PHI. - Assert2(&PN == &PN.getParent()->front() || + Assert2(&PN == &PN.getParent()->front() || isa<PHINode>(--BasicBlock::iterator(&PN)), "PHI nodes not grouped at top of basic block!", &PN, PN.getParent()); @@ -1404,9 +1506,9 @@ void Verifier::VerifyCallSite(CallSite CS) { // Check attributes on the varargs part. for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) { - Type *Ty = CS.getArgument(Idx-1)->getType(); + Type *Ty = CS.getArgument(Idx-1)->getType(); VerifyParameterAttrs(Attrs, Idx, Ty, false, I); - + if (Attrs.hasAttribute(Idx, Attribute::Nest)) { Assert1(!SawNest, "More than one parameter has attribute nest!", I); SawNest = true; @@ -1435,6 +1537,14 @@ void Verifier::VerifyCallSite(CallSite CS) { "Function has metadata parameter but isn't an intrinsic", I); } + // If the call site has the 'builtin' attribute, verify that it's applied to a + // direct call to a function with the 'nobuiltin' attribute. + if (CS.hasFnAttr(Attribute::Builtin)) + Assert1(CS.getCalledFunction() && + CS.getCalledFunction()->hasFnAttribute(Attribute::NoBuiltin), + "Attribute 'builtin' can only be used in a call to a function with " + "the 'nobuiltin' attribute.", I); + visitInstruction(*I); } @@ -1719,7 +1829,7 @@ void Verifier::visitStoreInst(StoreInst &SI) { void Verifier::visitAllocaInst(AllocaInst &AI) { PointerType *PTy = AI.getType(); - Assert1(PTy->getAddressSpace() == 0, + Assert1(PTy->getAddressSpace() == 0, "Allocation instruction pointer not in the generic address space!", &AI); Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type", @@ -1791,7 +1901,7 @@ void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { EVI.getIndices()) == EVI.getType(), "Invalid ExtractValueInst operands!", &EVI); - + visitInstruction(EVI); } @@ -1800,7 +1910,7 @@ void Verifier::visitInsertValueInst(InsertValueInst &IVI) { IVI.getIndices()) == IVI.getOperand(1)->getType(), "Invalid InsertValueInst operands!", &IVI); - + visitInstruction(IVI); } @@ -1887,7 +1997,7 @@ void Verifier::visitInstruction(Instruction &I) { // Check that the return value of the instruction is either void or a legal // value type. - Assert1(I.getType()->isVoidTy() || + Assert1(I.getType()->isVoidTy() || I.getType()->isFirstClassType(), "Instruction returns a non-scalar type!", &I); @@ -1945,6 +2055,27 @@ void Verifier::visitInstruction(Instruction &I) { Assert1((i + 1 == e && isa<CallInst>(I)) || (i + 3 == e && isa<InvokeInst>(I)), "Cannot take the address of an inline asm!", &I); + } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { + if (CE->getType()->isPtrOrPtrVectorTy()) { + // If we have a ConstantExpr pointer, we need to see if it came from an + // illegal bitcast (inttoptr <constant int> ) + SmallVector<const ConstantExpr *, 4> Stack; + SmallPtrSet<const ConstantExpr *, 4> Visited; + Stack.push_back(CE); + + while (!Stack.empty()) { + const ConstantExpr *V = Stack.pop_back_val(); + if (!Visited.insert(V)) + continue; + + VerifyConstantExprBitcastType(V); + + for (unsigned I = 0, N = V->getNumOperands(); I != N; ++I) { + if (ConstantExpr *Op = dyn_cast<ConstantExpr>(V->getOperand(I))) + Stack.push_back(Op); + } + } + } } } @@ -1955,7 +2086,7 @@ void Verifier::visitInstruction(Instruction &I) { Value *Op0 = MD->getOperand(0); if (ConstantFP *CFP0 = dyn_cast_or_null<ConstantFP>(Op0)) { APFloat Accuracy = CFP0->getValueAPF(); - Assert1(Accuracy.isNormal() && !Accuracy.isNegative(), + Assert1(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(), "fpmath accuracy not a positive number!", &I); } else { Assert1(false, "invalid fpmath accuracy!", &I); @@ -1965,6 +2096,11 @@ void Verifier::visitInstruction(Instruction &I) { MDNode *MD = I.getMetadata(LLVMContext::MD_range); Assert1(!MD || isa<LoadInst>(I), "Ranges are only for loads!", &I); + if (!DisableDebugInfoVerifier) { + MD = I.getMetadata(LLVMContext::MD_dbg); + Finder.processLocation(DILocation(MD)); + } + InstsInThisBlock.insert(&I); } @@ -1979,10 +2115,10 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, using namespace Intrinsic; // If we ran out of descriptors, there are too many arguments. - if (Infos.empty()) return true; + if (Infos.empty()) return true; IITDescriptor D = Infos.front(); Infos = Infos.slice(1); - + switch (D.Kind) { case IITDescriptor::Void: return !Ty->isVoidTy(); case IITDescriptor::MMX: return !Ty->isX86_MMXTy(); @@ -2001,29 +2137,29 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, return PT == 0 || PT->getAddressSpace() != D.Pointer_AddressSpace || VerifyIntrinsicType(PT->getElementType(), Infos, ArgTys); } - + case IITDescriptor::Struct: { StructType *ST = dyn_cast<StructType>(Ty); if (ST == 0 || ST->getNumElements() != D.Struct_NumElements) return true; - + for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) if (VerifyIntrinsicType(ST->getElementType(i), Infos, ArgTys)) return true; return false; } - + case IITDescriptor::Argument: // Two cases here - If this is the second occurrence of an argument, verify - // that the later instance matches the previous instance. + // that the later instance matches the previous instance. if (D.getArgumentNumber() < ArgTys.size()) - return Ty != ArgTys[D.getArgumentNumber()]; - + return Ty != ArgTys[D.getArgumentNumber()]; + // Otherwise, if this is the first instance of an argument, record it and // verify the "Any" kind. assert(D.getArgumentNumber() == ArgTys.size() && "Table consistency error"); ArgTys.push_back(Ty); - + switch (D.getArgumentKind()) { case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy(); case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy(); @@ -2031,7 +2167,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, case IITDescriptor::AK_AnyPointer: return !isa<PointerType>(Ty); } llvm_unreachable("all argument kinds not covered"); - + case IITDescriptor::ExtendVecArgument: // This may only be used when referring to a previous vector argument. return D.getArgumentNumber() >= ArgTys.size() || @@ -2060,7 +2196,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { // describe. FunctionType *IFTy = IF->getFunctionType(); Assert1(!IFTy->isVarArg(), "Intrinsic prototypes are not varargs", IF); - + SmallVector<Intrinsic::IITDescriptor, 8> Table; getIntrinsicInfoTableEntries(ID, Table); ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; @@ -2079,7 +2215,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { // the name. Assert1(Intrinsic::getName(ID, ArgTys) == IF->getName(), "Intrinsic name not mangled correctly for type arguments!", IF); - + // If the intrinsic takes MDNode arguments, verify that they are either global // or are local to *this* function. for (unsigned i = 0, e = CI.getNumArgOperands(); i != e; ++i) @@ -2101,7 +2237,17 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { MDNode *MD = cast<MDNode>(CI.getArgOperand(0)); Assert1(MD->getNumOperands() == 1, "invalid llvm.dbg.declare intrinsic call 2", &CI); + if (!DisableDebugInfoVerifier) + Finder.processDeclare(cast<DbgDeclareInst>(&CI)); } break; + case Intrinsic::dbg_value: { //llvm.dbg.value + if (!DisableDebugInfoVerifier) { + Assert1(CI.getArgOperand(0) && isa<MDNode>(CI.getArgOperand(0)), + "invalid llvm.dbg.value intrinsic call 1", &CI); + Finder.processValue(cast<DbgValueInst>(&CI)); + } + break; + } case Intrinsic::memcpy: case Intrinsic::memmove: case Intrinsic::memset: @@ -2163,6 +2309,30 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { } } +void Verifier::verifyDebugInfo(Module &M) { + // Verify Debug Info. + if (!DisableDebugInfoVerifier) { + Finder.processModule(M); + + for (DebugInfoFinder::iterator I = Finder.compile_unit_begin(), + E = Finder.compile_unit_end(); I != E; ++I) + Assert1(DICompileUnit(*I).Verify(), "DICompileUnit does not Verify!", *I); + for (DebugInfoFinder::iterator I = Finder.subprogram_begin(), + E = Finder.subprogram_end(); I != E; ++I) + Assert1(DISubprogram(*I).Verify(), "DISubprogram does not Verify!", *I); + for (DebugInfoFinder::iterator I = Finder.global_variable_begin(), + E = Finder.global_variable_end(); I != E; ++I) + Assert1(DIGlobalVariable(*I).Verify(), + "DIGlobalVariable does not Verify!", *I); + for (DebugInfoFinder::iterator I = Finder.type_begin(), + E = Finder.type_end(); I != E; ++I) + Assert1(DIType(*I).Verify(), "DIType does not Verify!", *I); + for (DebugInfoFinder::iterator I = Finder.scope_begin(), + E = Finder.scope_end(); I != E; ++I) + Assert1(DIScope(*I).Verify(), "DIScope does not Verify!", *I); + } +} + //===----------------------------------------------------------------------===// // Implement the public interfaces to this file... //===----------------------------------------------------------------------===// |