diff options
Diffstat (limited to 'contrib/llvm/lib/IR')
-rw-r--r-- | contrib/llvm/lib/IR/AsmWriter.cpp | 28 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/AttributeImpl.h | 20 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Attributes.cpp | 141 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Constants.cpp | 28 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/ConstantsContext.h | 2 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Core.cpp | 104 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/DIBuilder.cpp | 30 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/DataLayout.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/DebugInfo.cpp | 42 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Function.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Metadata.cpp | 36 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/PassManager.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Type.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Value.cpp | 10 | ||||
-rw-r--r-- | contrib/llvm/lib/IR/Verifier.cpp | 231 |
15 files changed, 443 insertions, 250 deletions
diff --git a/contrib/llvm/lib/IR/AsmWriter.cpp b/contrib/llvm/lib/IR/AsmWriter.cpp index fb591a8..7761127d 100644 --- a/contrib/llvm/lib/IR/AsmWriter.cpp +++ b/contrib/llvm/lib/IR/AsmWriter.cpp @@ -1605,6 +1605,29 @@ void AssemblyWriter::printFunction(const Function *F) { if (F->isMaterializable()) Out << "; Materializable\n"; + const AttributeSet &Attrs = F->getAttributes(); + if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) { + AttributeSet AS = Attrs.getFnAttributes(); + std::string AttrStr; + + unsigned Idx = 0; + for (unsigned E = AS.getNumSlots(); Idx != E; ++Idx) + if (AS.getSlotIndex(Idx) == AttributeSet::FunctionIndex) + break; + + for (AttributeSet::iterator I = AS.begin(Idx), E = AS.end(Idx); + I != E; ++I) { + Attribute Attr = *I; + if (!Attr.isStringAttribute()) { + if (!AttrStr.empty()) AttrStr += ' '; + AttrStr += Attr.getAsString(); + } + } + + if (!AttrStr.empty()) + Out << "; Function Attrs: " << AttrStr << '\n'; + } + if (F->isDeclaration()) Out << "declare "; else @@ -1620,7 +1643,6 @@ void AssemblyWriter::printFunction(const Function *F) { } FunctionType *FT = F->getFunctionType(); - const AttributeSet &Attrs = F->getAttributes(); if (Attrs.hasAttributes(AttributeSet::ReturnIndex)) Out << Attrs.getAsString(AttributeSet::ReturnIndex) << ' '; TypePrinter.print(F->getReturnType(), Out); @@ -1761,10 +1783,8 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { /// which slot it occupies. /// void AssemblyWriter::printInfoComment(const Value &V) { - if (AnnotationWriter) { + if (AnnotationWriter) AnnotationWriter->printInfoComment(V, Out); - return; - } } // This member is called for each Instruction in a function.. diff --git a/contrib/llvm/lib/IR/AttributeImpl.h b/contrib/llvm/lib/IR/AttributeImpl.h index ad2670d..0b6228b 100644 --- a/contrib/llvm/lib/IR/AttributeImpl.h +++ b/contrib/llvm/lib/IR/AttributeImpl.h @@ -228,7 +228,7 @@ public: /// 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. - uint64_t getSlotIndex(unsigned Slot) const { + unsigned getSlotIndex(unsigned Slot) const { return AttrNodes[Slot].first; } @@ -248,15 +248,15 @@ public: typedef AttributeSetNode::iterator iterator; typedef AttributeSetNode::const_iterator const_iterator; - iterator begin(unsigned Idx) - { return AttrNodes[Idx].second->begin(); } - iterator end(unsigned Idx) - { return AttrNodes[Idx].second->end(); } + iterator begin(unsigned Slot) + { return AttrNodes[Slot].second->begin(); } + iterator end(unsigned Slot) + { return AttrNodes[Slot].second->end(); } - const_iterator begin(unsigned Idx) const - { return AttrNodes[Idx].second->begin(); } - const_iterator end(unsigned Idx) const - { return AttrNodes[Idx].second->end(); } + const_iterator begin(unsigned Slot) const + { return AttrNodes[Slot].second->begin(); } + const_iterator end(unsigned Slot) const + { return AttrNodes[Slot].second->end(); } void Profile(FoldingSetNodeID &ID) const { Profile(ID, AttrNodes); @@ -270,7 +270,7 @@ public: } // FIXME: This atrocity is temporary. - uint64_t Raw(uint64_t Index) const; + uint64_t Raw(unsigned Index) const; }; } // end llvm namespace diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp index 2d82891..4fe6f9d 100644 --- a/contrib/llvm/lib/IR/Attributes.cpp +++ b/contrib/llvm/lib/IR/Attributes.cpp @@ -195,6 +195,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "readnone"; if (hasAttribute(Attribute::ReadOnly)) return "readonly"; + if (hasAttribute(Attribute::Returned)) + return "returned"; if (hasAttribute(Attribute::ReturnsTwice)) return "returns_twice"; if (hasAttribute(Attribute::SExt)) @@ -393,6 +395,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::SanitizeThread: return 1ULL << 36; case Attribute::SanitizeMemory: return 1ULL << 37; case Attribute::NoBuiltin: return 1ULL << 38; + case Attribute::Returned: return 1ULL << 39; } llvm_unreachable("Unsupported attribute type"); } @@ -481,11 +484,12 @@ unsigned AttributeSetNode::getStackAlignment() const { } std::string AttributeSetNode::getAsString(bool InAttrGrp) const { - std::string Str = ""; + std::string Str; for (SmallVectorImpl<Attribute>::const_iterator I = AttrList.begin(), - E = AttrList.end(); I != E; ) { + E = AttrList.end(); I != E; ++I) { + if (I != AttrList.begin()) + Str += ' '; Str += I->getAsString(InAttrGrp); - if (++I != E) Str += " "; } return Str; } @@ -494,7 +498,7 @@ std::string AttributeSetNode::getAsString(bool InAttrGrp) const { // AttributeSetImpl Definition //===----------------------------------------------------------------------===// -uint64_t AttributeSetImpl::Raw(uint64_t Index) 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; @@ -592,7 +596,7 @@ AttributeSet AttributeSet::get(LLVMContext &C, return getImpl(C, Attrs); } -AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, AttrBuilder &B) { +AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, AttrBuilder &B) { if (!B.hasAttributes()) return AttributeSet(); @@ -604,29 +608,29 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, AttrBuilder &B) { continue; if (Kind == Attribute::Alignment) - Attrs.push_back(std::make_pair(Idx, Attribute:: + Attrs.push_back(std::make_pair(Index, Attribute:: getWithAlignment(C, B.getAlignment()))); else if (Kind == Attribute::StackAlignment) - Attrs.push_back(std::make_pair(Idx, Attribute:: + Attrs.push_back(std::make_pair(Index, Attribute:: getWithStackAlignment(C, B.getStackAlignment()))); else - Attrs.push_back(std::make_pair(Idx, Attribute::get(C, Kind))); + Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind))); } // Add target-dependent (string) attributes. for (AttrBuilder::td_iterator I = B.td_begin(), E = B.td_end(); I != E; ++I) - Attrs.push_back(std::make_pair(Idx, Attribute::get(C, I->first,I->second))); + Attrs.push_back(std::make_pair(Index, Attribute::get(C, I->first,I->second))); return get(C, Attrs); } -AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, ArrayRef<Attribute::AttrKind> Kind) { SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; for (ArrayRef<Attribute::AttrKind>::iterator I = Kind.begin(), E = Kind.end(); I != E; ++I) - Attrs.push_back(std::make_pair(Idx, Attribute::get(C, *I))); + Attrs.push_back(std::make_pair(Index, Attribute::get(C, *I))); return get(C, Attrs); } @@ -643,20 +647,20 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) { return getImpl(C, AttrNodeVec); } -AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const { - if (hasAttribute(Idx, Attr)) return *this; - return addAttributes(C, Idx, AttributeSet::get(C, Idx, Attr)); + if (hasAttribute(Index, Attr)) return *this; + return addAttributes(C, Index, AttributeSet::get(C, Index, Attr)); } -AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const { llvm::AttrBuilder B; B.addAttribute(Kind); - return addAttributes(C, Idx, AttributeSet::get(C, Idx, B)); + return addAttributes(C, Index, AttributeSet::get(C, Index, B)); } -AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const { if (!pImpl) return Attrs; if (!Attrs.pImpl) return *this; @@ -664,8 +668,8 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, #ifndef NDEBUG // FIXME it is not obvious how this should work for alignment. For now, say // we can't change a known alignment. - unsigned OldAlign = getParamAlignment(Idx); - unsigned NewAlign = Attrs.getParamAlignment(Idx); + unsigned OldAlign = getParamAlignment(Index); + unsigned NewAlign = Attrs.getParamAlignment(Index); assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && "Attempt to change alignment!"); #endif @@ -676,8 +680,8 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, AttributeSet AS; uint64_t LastIndex = 0; for (unsigned I = 0, E = NumAttrs; I != E; ++I) { - if (getSlotIndex(I) >= Idx) { - if (getSlotIndex(I) == Idx) AS = getSlotAttributes(LastIndex++); + if (getSlotIndex(I) >= Index) { + if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); break; } LastIndex = I + 1; @@ -686,17 +690,17 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, // Now add the attribute into the correct slot. There may already be an // AttributeSet there. - AttrBuilder B(AS, Idx); + AttrBuilder B(AS, Index); for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) - if (Attrs.getSlotIndex(I) == Idx) { + if (Attrs.getSlotIndex(I) == Index) { for (AttributeSetImpl::const_iterator II = Attrs.pImpl->begin(I), IE = Attrs.pImpl->end(I); II != IE; ++II) B.addAttribute(*II); break; } - AttrSet.push_back(AttributeSet::get(C, Idx, B)); + AttrSet.push_back(AttributeSet::get(C, Index, B)); // Add the remaining attribute slots. for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) @@ -705,13 +709,13 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, return get(C, AttrSet); } -AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const { - if (!hasAttribute(Idx, Attr)) return *this; - return removeAttributes(C, Idx, AttributeSet::get(C, Idx, Attr)); + if (!hasAttribute(Index, Attr)) return *this; + return removeAttributes(C, Index, AttributeSet::get(C, Index, Attr)); } -AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, +AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const { if (!pImpl) return AttributeSet(); if (!Attrs.pImpl) return *this; @@ -719,7 +723,7 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, #ifndef NDEBUG // FIXME it is not obvious how this should work for alignment. // For now, say we can't pass in alignment, which no current use does. - assert(!Attrs.hasAttribute(Idx, Attribute::Alignment) && + assert(!Attrs.hasAttribute(Index, Attribute::Alignment) && "Attempt to change alignment!"); #endif @@ -729,8 +733,8 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, AttributeSet AS; uint64_t LastIndex = 0; for (unsigned I = 0, E = NumAttrs; I != E; ++I) { - if (getSlotIndex(I) >= Idx) { - if (getSlotIndex(I) == Idx) AS = getSlotAttributes(LastIndex++); + if (getSlotIndex(I) >= Index) { + if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); break; } LastIndex = I + 1; @@ -739,15 +743,15 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, // Now remove the attribute from the correct slot. There may already be an // AttributeSet there. - AttrBuilder B(AS, Idx); + AttrBuilder B(AS, Index); for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) - if (Attrs.getSlotIndex(I) == Idx) { - B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Idx); + if (Attrs.getSlotIndex(I) == Index) { + B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Index); break; } - AttrSet.push_back(AttributeSet::get(C, Idx, B)); + AttrSet.push_back(AttributeSet::get(C, Index, B)); // Add the remaining attribute slots. for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) @@ -764,11 +768,11 @@ LLVMContext &AttributeSet::getContext() const { return pImpl->getContext(); } -AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const { - return pImpl && hasAttributes(Idx) ? +AttributeSet AttributeSet::getParamAttributes(unsigned Index) const { + return pImpl && hasAttributes(Index) ? AttributeSet::get(pImpl->getContext(), ArrayRef<std::pair<unsigned, AttributeSetNode*> >( - std::make_pair(Idx, getAttributes(Idx)))) : + std::make_pair(Index, getAttributes(Index)))) : AttributeSet(); } @@ -848,27 +852,27 @@ std::string AttributeSet::getAsString(unsigned Index, } /// \brief The attributes for the specified index are returned. -AttributeSetNode *AttributeSet::getAttributes(unsigned Idx) const { +AttributeSetNode *AttributeSet::getAttributes(unsigned Index) const { if (!pImpl) return 0; // Loop through to find the attribute node we want. for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) - if (pImpl->getSlotIndex(I) == Idx) + if (pImpl->getSlotIndex(I) == Index) return pImpl->getSlotNode(I); return 0; } -AttributeSet::iterator AttributeSet::begin(unsigned Idx) const { +AttributeSet::iterator AttributeSet::begin(unsigned Slot) const { if (!pImpl) return ArrayRef<Attribute>().begin(); - return pImpl->begin(Idx); + return pImpl->begin(Slot); } -AttributeSet::iterator AttributeSet::end(unsigned Idx) const { +AttributeSet::iterator AttributeSet::end(unsigned Slot) const { if (!pImpl) return ArrayRef<Attribute>().end(); - return pImpl->end(Idx); + return pImpl->end(Slot); } //===----------------------------------------------------------------------===// @@ -882,7 +886,7 @@ unsigned AttributeSet::getNumSlots() const { return pImpl ? pImpl->getNumAttributes() : 0; } -uint64_t AttributeSet::getSlotIndex(unsigned Slot) const { +unsigned AttributeSet::getSlotIndex(unsigned Slot) const { assert(pImpl && Slot < pImpl->getNumAttributes() && "Slot # out of range!"); return pImpl->getSlotIndex(Slot); @@ -919,13 +923,13 @@ void AttributeSet::dump() const { // AttrBuilder Method Implementations //===----------------------------------------------------------------------===// -AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Idx) +AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) : Attrs(0), Alignment(0), StackAlignment(0) { AttributeSetImpl *pImpl = AS.pImpl; if (!pImpl) return; for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) { - if (pImpl->getSlotIndex(I) != Idx) continue; + if (pImpl->getSlotIndex(I) != Index) continue; for (AttributeSetImpl::const_iterator II = pImpl->begin(I), IE = pImpl->end(I); II != IE; ++II) @@ -982,16 +986,16 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { } AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) { - unsigned Idx = ~0U; + unsigned Slot = ~0U; for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I) if (A.getSlotIndex(I) == Index) { - Idx = I; + Slot = I; break; } - assert(Idx != ~0U && "Couldn't find index in AttributeSet!"); + assert(Slot != ~0U && "Couldn't find index in AttributeSet!"); - for (AttributeSet::iterator I = A.begin(Idx), E = A.end(Idx); I != E; ++I) { + for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { Attribute Attr = *I; if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { Attribute::AttrKind Kind = I->getKindAsEnum(); @@ -1069,16 +1073,16 @@ bool AttrBuilder::hasAttributes() const { } bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const { - unsigned Idx = ~0U; + unsigned Slot = ~0U; for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I) if (A.getSlotIndex(I) == Index) { - Idx = I; + Slot = I; break; } - assert(Idx != ~0U && "Couldn't find the index!"); + assert(Slot != ~0U && "Couldn't find the index!"); - for (AttributeSet::iterator I = A.begin(Idx), E = A.end(Idx); + for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { Attribute Attr = *I; if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { @@ -1109,33 +1113,6 @@ bool AttrBuilder::operator==(const AttrBuilder &B) { return Alignment == B.Alignment && StackAlignment == B.StackAlignment; } -void AttrBuilder::removeFunctionOnlyAttrs() { - removeAttribute(Attribute::NoReturn) - .removeAttribute(Attribute::NoUnwind) - .removeAttribute(Attribute::ReadNone) - .removeAttribute(Attribute::ReadOnly) - .removeAttribute(Attribute::NoInline) - .removeAttribute(Attribute::AlwaysInline) - .removeAttribute(Attribute::OptimizeForSize) - .removeAttribute(Attribute::StackProtect) - .removeAttribute(Attribute::StackProtectReq) - .removeAttribute(Attribute::StackProtectStrong) - .removeAttribute(Attribute::NoRedZone) - .removeAttribute(Attribute::NoImplicitFloat) - .removeAttribute(Attribute::Naked) - .removeAttribute(Attribute::InlineHint) - .removeAttribute(Attribute::StackAlignment) - .removeAttribute(Attribute::UWTable) - .removeAttribute(Attribute::NonLazyBind) - .removeAttribute(Attribute::ReturnsTwice) - .removeAttribute(Attribute::SanitizeAddress) - .removeAttribute(Attribute::SanitizeThread) - .removeAttribute(Attribute::SanitizeMemory) - .removeAttribute(Attribute::MinSize) - .removeAttribute(Attribute::NoDuplicate) - .removeAttribute(Attribute::NoBuiltin); -} - AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { // FIXME: Remove this in 4.0. if (!Val) return *this; diff --git a/contrib/llvm/lib/IR/Constants.cpp b/contrib/llvm/lib/IR/Constants.cpp index 1abb656..2c6971c 100644 --- a/contrib/llvm/lib/IR/Constants.cpp +++ b/contrib/llvm/lib/IR/Constants.cpp @@ -237,18 +237,21 @@ void Constant::destroyConstantImpl() { delete this; } -/// canTrap - Return true if evaluation of this constant could trap. This is -/// true for things like constant expressions that could divide by zero. -bool Constant::canTrap() const { - assert(getType()->isFirstClassType() && "Cannot evaluate aggregate vals!"); +static bool canTrapImpl(const Constant *C, + SmallPtrSet<const ConstantExpr *, 4> &NonTrappingOps) { + assert(C->getType()->isFirstClassType() && "Cannot evaluate aggregate vals!"); // The only thing that could possibly trap are constant exprs. - const ConstantExpr *CE = dyn_cast<ConstantExpr>(this); - if (!CE) return false; + const ConstantExpr *CE = dyn_cast<ConstantExpr>(C); + if (!CE) + return false; // ConstantExpr traps if any operands can trap. - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (CE->getOperand(i)->canTrap()) - return true; + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { + if (ConstantExpr *Op = dyn_cast<ConstantExpr>(CE->getOperand(i))) { + if (NonTrappingOps.insert(Op) && canTrapImpl(Op, NonTrappingOps)) + return true; + } + } // Otherwise, only specific operations can trap. switch (CE->getOpcode()) { @@ -267,6 +270,13 @@ bool Constant::canTrap() const { } } +/// canTrap - Return true if evaluation of this constant could trap. This is +/// true for things like constant expressions that could divide by zero. +bool Constant::canTrap() const { + SmallPtrSet<const ConstantExpr *, 4> NonTrappingOps; + return canTrapImpl(this, NonTrappingOps); +} + /// isThreadDependent - Return true if the value can vary between threads. bool Constant::isThreadDependent() const { SmallPtrSet<const Constant*, 64> Visited; diff --git a/contrib/llvm/lib/IR/ConstantsContext.h b/contrib/llvm/lib/IR/ConstantsContext.h index e995858..32bed95 100644 --- a/contrib/llvm/lib/IR/ConstantsContext.h +++ b/contrib/llvm/lib/IR/ConstantsContext.h @@ -318,7 +318,7 @@ struct ExprMapKeyType { ArrayRef<Constant*> ops, unsigned short flags = 0, unsigned short optionalflags = 0, - ArrayRef<unsigned> inds = ArrayRef<unsigned>()) + ArrayRef<unsigned> inds = None) : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {} uint8_t opcode; diff --git a/contrib/llvm/lib/IR/Core.cpp b/contrib/llvm/lib/IR/Core.cpp index 983b49c..889d574 100644 --- a/contrib/llvm/lib/IR/Core.cpp +++ b/contrib/llvm/lib/IR/Core.cpp @@ -21,7 +21,9 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/PassManager.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" @@ -1301,6 +1303,53 @@ void LLVMSetGlobalConstant(LLVMValueRef GlobalVar, LLVMBool IsConstant) { unwrap<GlobalVariable>(GlobalVar)->setConstant(IsConstant != 0); } +LLVMThreadLocalMode LLVMGetThreadLocalMode(LLVMValueRef GlobalVar) { + switch (unwrap<GlobalVariable>(GlobalVar)->getThreadLocalMode()) { + case GlobalVariable::NotThreadLocal: + return LLVMNotThreadLocal; + case GlobalVariable::GeneralDynamicTLSModel: + return LLVMGeneralDynamicTLSModel; + case GlobalVariable::LocalDynamicTLSModel: + return LLVMLocalDynamicTLSModel; + case GlobalVariable::InitialExecTLSModel: + return LLVMInitialExecTLSModel; + case GlobalVariable::LocalExecTLSModel: + return LLVMLocalExecTLSModel; + } + + llvm_unreachable("Invalid GlobalVariable thread local mode"); +} + +void LLVMSetThreadLocalMode(LLVMValueRef GlobalVar, LLVMThreadLocalMode Mode) { + GlobalVariable *GV = unwrap<GlobalVariable>(GlobalVar); + + switch (Mode) { + case LLVMNotThreadLocal: + GV->setThreadLocalMode(GlobalVariable::NotThreadLocal); + break; + case LLVMGeneralDynamicTLSModel: + GV->setThreadLocalMode(GlobalVariable::GeneralDynamicTLSModel); + break; + case LLVMLocalDynamicTLSModel: + GV->setThreadLocalMode(GlobalVariable::LocalDynamicTLSModel); + break; + case LLVMInitialExecTLSModel: + GV->setThreadLocalMode(GlobalVariable::InitialExecTLSModel); + break; + case LLVMLocalExecTLSModel: + GV->setThreadLocalMode(GlobalVariable::LocalExecTLSModel); + break; + } +} + +LLVMBool LLVMIsExternallyInitialized(LLVMValueRef GlobalVar) { + return unwrap<GlobalVariable>(GlobalVar)->isExternallyInitialized(); +} + +void LLVMSetExternallyInitialized(LLVMValueRef GlobalVar, LLVMBool IsExtInit) { + unwrap<GlobalVariable>(GlobalVar)->setExternallyInitialized(IsExtInit); +} + /*--.. Operations on aliases ......................................--*/ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, @@ -1396,6 +1445,18 @@ void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Func->setAttributes(PALnew); } +void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, + const char *V) { + Function *Func = unwrap<Function>(Fn); + AttributeSet::AttrIndex Idx = + AttributeSet::AttrIndex(AttributeSet::FunctionIndex); + AttrBuilder B; + + B.addAttribute(A, V); + AttributeSet Set = AttributeSet::get(Func->getContext(), Idx, B); + Func->addAttributes(Idx, Set); +} + void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Function *Func = unwrap<Function>(Fn); const AttributeSet PAL = Func->getAttributes(); @@ -2331,6 +2392,42 @@ LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef B, LLVMValueRef LHS, return wrap(unwrap(B)->CreatePtrDiff(unwrap(LHS), unwrap(RHS), Name)); } +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, + LLVMValueRef PTR, LLVMValueRef Val, + LLVMAtomicOrdering ordering, + LLVMBool singleThread) { + AtomicRMWInst::BinOp intop; + switch (op) { + case LLVMAtomicRMWBinOpXchg: intop = AtomicRMWInst::Xchg; break; + case LLVMAtomicRMWBinOpAdd: intop = AtomicRMWInst::Add; break; + case LLVMAtomicRMWBinOpSub: intop = AtomicRMWInst::Sub; break; + case LLVMAtomicRMWBinOpAnd: intop = AtomicRMWInst::And; break; + case LLVMAtomicRMWBinOpNand: intop = AtomicRMWInst::Nand; break; + case LLVMAtomicRMWBinOpOr: intop = AtomicRMWInst::Or; break; + case LLVMAtomicRMWBinOpXor: intop = AtomicRMWInst::Xor; break; + case LLVMAtomicRMWBinOpMax: intop = AtomicRMWInst::Max; break; + case LLVMAtomicRMWBinOpMin: intop = AtomicRMWInst::Min; break; + case LLVMAtomicRMWBinOpUMax: intop = AtomicRMWInst::UMax; break; + case LLVMAtomicRMWBinOpUMin: intop = AtomicRMWInst::UMin; break; + } + AtomicOrdering intordering; + switch (ordering) { + case LLVMAtomicOrderingNotAtomic: intordering = NotAtomic; break; + case LLVMAtomicOrderingUnordered: intordering = Unordered; break; + case LLVMAtomicOrderingMonotonic: intordering = Monotonic; break; + case LLVMAtomicOrderingAcquire: intordering = Acquire; break; + case LLVMAtomicOrderingRelease: intordering = Release; break; + case LLVMAtomicOrderingAcquireRelease: + intordering = AcquireRelease; + break; + case LLVMAtomicOrderingSequentiallyConsistent: + intordering = SequentiallyConsistent; + break; + } + return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val), + intordering, singleThread ? SingleThread : CrossThread)); +} + /*===-- Module providers --------------------------------------------------===*/ @@ -2397,6 +2494,13 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy( StringRef(BufferName))); } +const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf) { + return unwrap(MemBuf)->getBufferStart(); +} + +size_t LLVMGetBufferSize(LLVMMemoryBufferRef MemBuf) { + return unwrap(MemBuf)->getBufferSize(); +} void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf) { delete unwrap(MemBuf); diff --git a/contrib/llvm/lib/IR/DIBuilder.cpp b/contrib/llvm/lib/IR/DIBuilder.cpp index 9d6e840..0980e80 100644 --- a/contrib/llvm/lib/IR/DIBuilder.cpp +++ b/contrib/llvm/lib/IR/DIBuilder.cpp @@ -61,6 +61,9 @@ void DIBuilder::finalize() { DIArray GVs = getOrCreateArray(AllGVs); DIType(TempGVs).replaceAllUsesWith(GVs); + + DIArray IMs = getOrCreateArray(AllImportedModules); + DIType(TempImportedModules).replaceAllUsesWith(IMs); } /// getNonCompileUnitScope - If N is compile unit return NULL otherwise return @@ -101,6 +104,8 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, TempGVs = MDNode::getTemporary(VMContext, TElts); + TempImportedModules = MDNode::getTemporary(VMContext, TElts); + Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), createFilePathPair(VMContext, Filename, Directory), @@ -113,6 +118,7 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, TempRetainTypes, TempSubprograms, TempGVs, + TempImportedModules, MDString::get(VMContext, SplitName) }; TheCU = DICompileUnit(MDNode::get(VMContext, Elts)); @@ -122,6 +128,21 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, NMD->addOperand(TheCU); } +DIImportedModule DIBuilder::createImportedModule(DIScope Context, + DINameSpace NS, + unsigned Line) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_imported_module), + Context, + NS, + ConstantInt::get(Type::getInt32Ty(VMContext), Line), + }; + DIImportedModule M(MDNode::get(VMContext, Elts)); + assert(M.Verify() && "Imported module should be valid"); + AllImportedModules.push_back(M); + return M; +} + /// createFile - Create a file descriptor to hold debugging information /// for a file. DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { @@ -225,7 +246,8 @@ DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, return DIDerivedType(MDNode::get(VMContext, Elts)); } -DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy, DIType Base) { +DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy, + DIType Base) { // Pointer types are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_ptr_to_member_type), @@ -427,7 +449,7 @@ DIType DIBuilder::createObjCIVar(StringRef Name, DIObjCProperty DIBuilder::createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber, StringRef GetterName, - StringRef SetterName, + StringRef SetterName, unsigned PropertyAttributes, DIType Ty) { Value *Elts[] = { @@ -601,7 +623,7 @@ DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { DICompositeType DIBuilder::createEnumerationType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, - DIType ClassType) { + DIType UnderlyingType) { // TAG_enumeration_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), @@ -613,7 +635,7 @@ DICompositeType DIBuilder::createEnumerationType( ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), ConstantInt::get(Type::getInt32Ty(VMContext), 0), ConstantInt::get(Type::getInt32Ty(VMContext), 0), - ClassType, + UnderlyingType, Elements, ConstantInt::get(Type::getInt32Ty(VMContext), 0), Constant::getNullValue(Type::getInt32Ty(VMContext)) diff --git a/contrib/llvm/lib/IR/DataLayout.cpp b/contrib/llvm/lib/IR/DataLayout.cpp index ecd5216..5658f56 100644 --- a/contrib/llvm/lib/IR/DataLayout.cpp +++ b/contrib/llvm/lib/IR/DataLayout.cpp @@ -41,7 +41,7 @@ char DataLayout::ID = 0; // Support for StructLayout //===----------------------------------------------------------------------===// -StructLayout::StructLayout(StructType *ST, const DataLayout &TD) { +StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { assert(!ST->isOpaque() && "Cannot get layout of opaque structs"); StructAlignment = 0; StructSize = 0; @@ -50,7 +50,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &TD) { // Loop over each of the elements, placing them in memory. for (unsigned i = 0, e = NumElements; i != e; ++i) { Type *Ty = ST->getElementType(i); - unsigned TyAlign = ST->isPacked() ? 1 : TD.getABITypeAlignment(Ty); + unsigned TyAlign = ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty); // Add padding if necessary to align the data element properly. if ((StructSize & (TyAlign-1)) != 0) @@ -60,7 +60,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &TD) { StructAlignment = std::max(TyAlign, StructAlignment); MemberOffsets[i] = StructSize; - StructSize += TD.getTypeAllocSize(Ty); // Consume space for this data item + StructSize += DL.getTypeAllocSize(Ty); // Consume space for this data item } // Empty structures have alignment of 1 byte. diff --git a/contrib/llvm/lib/IR/DebugInfo.cpp b/contrib/llvm/lib/IR/DebugInfo.cpp index 0ffe99d..ec83dca 100644 --- a/contrib/llvm/lib/IR/DebugInfo.cpp +++ b/contrib/llvm/lib/IR/DebugInfo.cpp @@ -64,7 +64,8 @@ bool DIDescriptor::Verify() const { DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() || DIObjCProperty(DbgNode).Verify() || DITemplateTypeParameter(DbgNode).Verify() || - DITemplateValueParameter(DbgNode).Verify()); + DITemplateValueParameter(DbgNode).Verify() || + DIImportedModule(DbgNode).Verify()); } static Value *getField(const MDNode *DbgNode, unsigned Elt) { @@ -336,6 +337,12 @@ bool DIDescriptor::isEnumerator() const { bool DIDescriptor::isObjCProperty() const { return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; } + +/// \brief Return true if the specified tag is DW_TAG_imported_module. +bool DIDescriptor::isImportedModule() const { + return DbgNode && getTag() == dwarf::DW_TAG_imported_module; +} + //===----------------------------------------------------------------------===// // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// @@ -418,7 +425,7 @@ bool DICompileUnit::Verify() const { if (N.empty()) return false; // It is possible that directory and produce string is empty. - return DbgNode->getNumOperands() == 12; + return DbgNode->getNumOperands() == 13; } /// Verify - Verify that an ObjC property is well formed. @@ -580,6 +587,11 @@ bool DITemplateValueParameter::Verify() const { return isTemplateValueParameter() && DbgNode->getNumOperands() == 8; } +/// \brief Verify that the imported module descriptor is well formed. +bool DIImportedModule::Verify() const { + return isImportedModule() && DbgNode->getNumOperands() == 4; +} + /// getOriginalTypeSize - If this type is derived from a base type then /// return base type size. uint64_t DIDerivedType::getOriginalTypeSize() const { @@ -694,7 +706,7 @@ StringRef DIScope::getDirectory() const { } DIArray DICompileUnit::getEnumTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 12) + if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(7))) @@ -703,7 +715,7 @@ DIArray DICompileUnit::getEnumTypes() const { } DIArray DICompileUnit::getRetainedTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 12) + if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(8))) @@ -712,7 +724,7 @@ DIArray DICompileUnit::getRetainedTypes() const { } DIArray DICompileUnit::getSubprograms() const { - if (!DbgNode || DbgNode->getNumOperands() < 12) + if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(9))) @@ -722,7 +734,7 @@ DIArray DICompileUnit::getSubprograms() const { DIArray DICompileUnit::getGlobalVariables() const { - if (!DbgNode || DbgNode->getNumOperands() < 12) + if (!DbgNode || DbgNode->getNumOperands() < 13) return DIArray(); if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(10))) @@ -730,6 +742,15 @@ DIArray DICompileUnit::getGlobalVariables() const { return DIArray(); } +DIArray DICompileUnit::getImportedModules() const { + if (!DbgNode || DbgNode->getNumOperands() < 13) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(11))) + return DIArray(N); + return DIArray(); +} + /// fixupObjcLikeName - Replace contains special characters used /// in a typical Objective-C names with '.' in a given string. static void fixupObjcLikeName(StringRef Str, SmallVectorImpl<char> &Out) { @@ -1054,8 +1075,13 @@ void DIScope::printInternal(raw_ostream &OS) const { void DICompileUnit::printInternal(raw_ostream &OS) const { DIScope::printInternal(OS); - if (const char *Lang = dwarf::LanguageString(getLanguage())) - OS << " [" << Lang << ']'; + OS << " ["; + unsigned Lang = getLanguage(); + if (const char *LangStr = dwarf::LanguageString(Lang)) + OS << LangStr; + else + (OS << "lang 0x").write_hex(Lang); + OS << ']'; } void DIEnumerator::printInternal(raw_ostream &OS) const { diff --git a/contrib/llvm/lib/IR/Function.cpp b/contrib/llvm/lib/IR/Function.cpp index 1e72b90..7f7efab 100644 --- a/contrib/llvm/lib/IR/Function.cpp +++ b/contrib/llvm/lib/IR/Function.cpp @@ -124,6 +124,13 @@ bool Argument::hasStructRetAttr() const { hasAttribute(1, Attribute::StructRet); } +/// hasReturnedAttr - Return true if this argument has the returned attribute on +/// it in its containing function. +bool Argument::hasReturnedAttr() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::Returned); +} + /// addAttr - Add attributes to an argument. void Argument::addAttr(AttributeSet AS) { assert(AS.getNumSlots() <= 1 && diff --git a/contrib/llvm/lib/IR/Metadata.cpp b/contrib/llvm/lib/IR/Metadata.cpp index 0228aeb..6a6b7af 100644 --- a/contrib/llvm/lib/IR/Metadata.cpp +++ b/contrib/llvm/lib/IR/Metadata.cpp @@ -403,42 +403,6 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { } } -MDNode *MDNode::getMostGenericTBAA(MDNode *A, MDNode *B) { - if (!A || !B) - return NULL; - - if (A == B) - return A; - - SmallVector<MDNode *, 4> PathA; - MDNode *T = A; - while (T) { - PathA.push_back(T); - T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0; - } - - SmallVector<MDNode *, 4> PathB; - T = B; - while (T) { - PathB.push_back(T); - T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0; - } - - int IA = PathA.size() - 1; - int IB = PathB.size() - 1; - - MDNode *Ret = 0; - while (IA >= 0 && IB >=0) { - if (PathA[IA] == PathB[IB]) - Ret = PathA[IA]; - else - break; - --IA; - --IB; - } - return Ret; -} - MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) { if (!A || !B) return NULL; diff --git a/contrib/llvm/lib/IR/PassManager.cpp b/contrib/llvm/lib/IR/PassManager.cpp index 3c968aa..387094a 100644 --- a/contrib/llvm/lib/IR/PassManager.cpp +++ b/contrib/llvm/lib/IR/PassManager.cpp @@ -42,14 +42,14 @@ namespace llvm { // Different debug levels that can be enabled... enum PassDebugLevel { - None, Arguments, Structure, Executions, Details + Disabled, Arguments, Structure, Executions, Details }; static cl::opt<enum PassDebugLevel> PassDebugging("debug-pass", cl::Hidden, cl::desc("Print PassManager debugging information"), cl::values( - clEnumVal(None , "disable debug output"), + clEnumVal(Disabled , "disable debug output"), clEnumVal(Arguments , "print pass arguments to pass to 'opt'"), clEnumVal(Structure , "print pass structure before run()"), clEnumVal(Executions, "print pass name before it is executed"), diff --git a/contrib/llvm/lib/IR/Type.cpp b/contrib/llvm/lib/IR/Type.cpp index 1e6a51a..46c61fc 100644 --- a/contrib/llvm/lib/IR/Type.cpp +++ b/contrib/llvm/lib/IR/Type.cpp @@ -380,7 +380,7 @@ FunctionType *FunctionType::get(Type *ReturnType, } FunctionType *FunctionType::get(Type *Result, bool isVarArg) { - return get(Result, ArrayRef<Type *>(), isVarArg); + return get(Result, None, isVarArg); } /// isValidReturnType - Return true if the specified type is valid as a return @@ -499,7 +499,7 @@ StructType *StructType::create(LLVMContext &Context, StringRef Name) { } StructType *StructType::get(LLVMContext &Context, bool isPacked) { - return get(Context, llvm::ArrayRef<Type*>(), isPacked); + return get(Context, None, isPacked); } StructType *StructType::get(Type *type, ...) { diff --git a/contrib/llvm/lib/IR/Value.cpp b/contrib/llvm/lib/IR/Value.cpp index adc702e..89a3c05 100644 --- a/contrib/llvm/lib/IR/Value.cpp +++ b/contrib/llvm/lib/IR/Value.cpp @@ -118,7 +118,7 @@ bool Value::isUsedInBasicBlock(const BasicBlock *BB) const { for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (std::find(I->op_begin(), I->op_end(), this) != I->op_end()) return true; - if (MaxBlockSize-- == 0) // If the block is larger fall back to use_iterator + if (--MaxBlockSize == 0) // If the block is larger fall back to use_iterator break; } @@ -333,6 +333,7 @@ namespace { // Various metrics for how much to strip off of pointers. enum PointerStripKind { PSK_ZeroIndices, + PSK_ZeroIndicesAndAliases, PSK_InBoundsConstantIndices, PSK_InBounds }; @@ -350,6 +351,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) { do { if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { switch (StripKind) { + case PSK_ZeroIndicesAndAliases: case PSK_ZeroIndices: if (!GEP->hasAllZeroIndices()) return V; @@ -367,7 +369,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) { } else if (Operator::getOpcode(V) == Instruction::BitCast) { V = cast<Operator>(V)->getOperand(0); } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { - if (GA->mayBeOverridden()) + if (StripKind == PSK_ZeroIndices || GA->mayBeOverridden()) return V; V = GA->getAliasee(); } else { @@ -381,6 +383,10 @@ static Value *stripPointerCastsAndOffsets(Value *V) { } // namespace Value *Value::stripPointerCasts() { + return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this); +} + +Value *Value::stripPointerCastsNoFollowAliases() { return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this); } diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp index 8bfbb32..d106173 100644 --- a/contrib/llvm/lib/IR/Verifier.cpp +++ b/contrib/llvm/lib/IR/Verifier.cpp @@ -301,9 +301,12 @@ namespace { bool VerifyIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos, SmallVectorImpl<Type*> &ArgTys); - void VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty, + bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params); + void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, + bool isFunction, const Value *V); + void VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, bool isReturnValue, const Value *V); - void VerifyFunctionAttrs(FunctionType *FT, const AttributeSet &Attrs, + void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V); void WriteValue(const Value *V) { @@ -446,6 +449,30 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { } } + if (GV.hasName() && (GV.getName() == "llvm.used" || + GV.getName() == "llvm.compiler_used")) { + Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(), + "invalid linkage for intrinsic global variable", &GV); + Type *GVType = GV.getType()->getElementType(); + if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) { + PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType()); + Assert1(PTy, "wrong type for intrinsic global variable", &GV); + if (GV.hasInitializer()) { + Constant *Init = GV.getInitializer(); + ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); + Assert1(InitArray, "wrong initalizer for intrinsic global variable", + Init); + for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) { + Value *V = Init->getOperand(i)->stripPointerCasts(); + // stripPointerCasts strips aliases, so we only need to check for + // variables and functions. + Assert1(isa<GlobalVariable>(V) || isa<Function>(V), + "invalid llvm.used member", V); + } + } + } + } + visitGlobalValue(GV); } @@ -626,44 +653,74 @@ void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs, } } +void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, + bool isFunction, const Value* V) { + unsigned Slot = ~0U; + for (unsigned I = 0, E = Attrs.getNumSlots(); I != E; ++I) + if (Attrs.getSlotIndex(I) == Idx) { + Slot = I; + break; + } + + assert(Slot != ~0U && "Attribute set inconsistency!"); + + for (AttributeSet::iterator I = Attrs.begin(Slot), E = Attrs.end(Slot); + I != E; ++I) { + if (I->isStringAttribute()) + continue; + + 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 || + I->getKindAsEnum() == Attribute::StackProtect || + I->getKindAsEnum() == Attribute::StackProtectReq || + I->getKindAsEnum() == Attribute::StackProtectStrong || + I->getKindAsEnum() == Attribute::NoRedZone || + I->getKindAsEnum() == Attribute::NoImplicitFloat || + I->getKindAsEnum() == Attribute::Naked || + I->getKindAsEnum() == Attribute::InlineHint || + I->getKindAsEnum() == Attribute::StackAlignment || + I->getKindAsEnum() == Attribute::UWTable || + I->getKindAsEnum() == Attribute::NonLazyBind || + I->getKindAsEnum() == Attribute::ReturnsTwice || + I->getKindAsEnum() == Attribute::SanitizeAddress || + I->getKindAsEnum() == Attribute::SanitizeThread || + I->getKindAsEnum() == Attribute::SanitizeMemory || + I->getKindAsEnum() == Attribute::MinSize || + I->getKindAsEnum() == Attribute::NoDuplicate || + I->getKindAsEnum() == Attribute::NoBuiltin) { + 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); + return; + } + } +} + // VerifyParameterAttrs - Check the given attributes for an argument or return // value of the specified type. The value V is printed in error messages. -void Verifier::VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty, +void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, bool isReturnValue, const Value *V) { if (!Attrs.hasAttributes(Idx)) return; - Assert1(!Attrs.hasAttribute(Idx, Attribute::NoReturn) && - !Attrs.hasAttribute(Idx, Attribute::NoUnwind) && - !Attrs.hasAttribute(Idx, Attribute::ReadNone) && - !Attrs.hasAttribute(Idx, Attribute::ReadOnly) && - !Attrs.hasAttribute(Idx, Attribute::NoInline) && - !Attrs.hasAttribute(Idx, Attribute::AlwaysInline) && - !Attrs.hasAttribute(Idx, Attribute::OptimizeForSize) && - !Attrs.hasAttribute(Idx, Attribute::StackProtect) && - !Attrs.hasAttribute(Idx, Attribute::StackProtectReq) && - !Attrs.hasAttribute(Idx, Attribute::NoRedZone) && - !Attrs.hasAttribute(Idx, Attribute::NoImplicitFloat) && - !Attrs.hasAttribute(Idx, Attribute::Naked) && - !Attrs.hasAttribute(Idx, Attribute::InlineHint) && - !Attrs.hasAttribute(Idx, Attribute::StackAlignment) && - !Attrs.hasAttribute(Idx, Attribute::UWTable) && - !Attrs.hasAttribute(Idx, Attribute::NonLazyBind) && - !Attrs.hasAttribute(Idx, Attribute::ReturnsTwice) && - !Attrs.hasAttribute(Idx, Attribute::SanitizeAddress) && - !Attrs.hasAttribute(Idx, Attribute::SanitizeThread) && - !Attrs.hasAttribute(Idx, Attribute::SanitizeMemory) && - !Attrs.hasAttribute(Idx, Attribute::MinSize) && - !Attrs.hasAttribute(Idx, Attribute::NoBuiltin), - "Some attributes in '" + Attrs.getAsString(Idx) + - "' only apply to functions!", V); + VerifyAttributeTypes(Attrs, Idx, false, V); if (isReturnValue) Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) && !Attrs.hasAttribute(Idx, Attribute::Nest) && !Attrs.hasAttribute(Idx, Attribute::StructRet) && - !Attrs.hasAttribute(Idx, Attribute::NoCapture), - "Attribute 'byval', 'nest', 'sret', and 'nocapture' " + !Attrs.hasAttribute(Idx, Attribute::NoCapture) && + !Attrs.hasAttribute(Idx, Attribute::Returned), + "Attribute 'byval', 'nest', 'sret', 'nocapture', and 'returned' " "do not apply to return values!", V); // Check for mutually incompatible attributes. @@ -683,6 +740,10 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty, Attrs.hasAttribute(Idx, Attribute::InReg))), "Attributes " "'byval, nest, and inreg' are incompatible!", V); + Assert1(!(Attrs.hasAttribute(Idx, Attribute::StructRet) && + Attrs.hasAttribute(Idx, Attribute::Returned)), "Attributes " + "'sret and returned' are incompatible!", V); + Assert1(!(Attrs.hasAttribute(Idx, Attribute::ZExt) && Attrs.hasAttribute(Idx, Attribute::SExt)), "Attributes " "'zeroext and signext' are incompatible!", V); @@ -712,81 +773,51 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty, // VerifyFunctionAttrs - Check parameter attributes against a function type. // The value V is printed in error messages. -void Verifier::VerifyFunctionAttrs(FunctionType *FT, - const AttributeSet &Attrs, +void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V) { if (Attrs.isEmpty()) return; bool SawNest = false; + bool SawReturned = false; for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { - unsigned Index = Attrs.getSlotIndex(i); + unsigned Idx = Attrs.getSlotIndex(i); Type *Ty; - if (Index == 0) + if (Idx == 0) Ty = FT->getReturnType(); - else if (Index-1 < FT->getNumParams()) - Ty = FT->getParamType(Index-1); + else if (Idx-1 < FT->getNumParams()) + Ty = FT->getParamType(Idx-1); else break; // VarArgs attributes, verified elsewhere. - VerifyParameterAttrs(Attrs, Index, Ty, Index == 0, V); + VerifyParameterAttrs(Attrs, Idx, Ty, Idx == 0, V); - if (Attrs.hasAttribute(i, Attribute::Nest)) { + if (Idx == 0) + continue; + + if (Attrs.hasAttribute(Idx, Attribute::Nest)) { Assert1(!SawNest, "More than one parameter has attribute nest!", V); SawNest = true; } - if (Attrs.hasAttribute(Index, Attribute::StructRet)) - Assert1(Index == 1, "Attribute sret is not on first parameter!", V); + if (Attrs.hasAttribute(Idx, Attribute::Returned)) { + Assert1(!SawReturned, "More than one parameter has attribute returned!", + V); + Assert1(Ty->canLosslesslyBitCastTo(FT->getReturnType()), "Incompatible " + "argument and return types for 'returned' attribute", V); + SawReturned = true; + } + + if (Attrs.hasAttribute(Idx, Attribute::StructRet)) + Assert1(Idx == 1, "Attribute sret is not on first parameter!", V); } if (!Attrs.hasAttributes(AttributeSet::FunctionIndex)) return; - AttrBuilder NotFn(Attrs, AttributeSet::FunctionIndex); - NotFn.removeFunctionOnlyAttrs(); - Assert1(NotFn.empty(), "Attributes '" + - AttributeSet::get(V->getContext(), - AttributeSet::FunctionIndex, - NotFn).getAsString(AttributeSet::FunctionIndex) + - "' do not apply to the function!", V); - - // Check for mutually incompatible attributes. - Assert1(!((Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ByVal) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::Nest)) || - (Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ByVal) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::StructRet)) || - (Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::Nest) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::StructRet))), - "Attributes 'byval, nest, and sret' are incompatible!", V); - - Assert1(!((Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ByVal) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::Nest)) || - (Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ByVal) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::InReg)) || - (Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::Nest) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::InReg))), - "Attributes 'byval, nest, and inreg' are incompatible!", V); - - Assert1(!(Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ZExt) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::SExt)), - "Attributes 'zeroext and signext' are incompatible!", V); + VerifyAttributeTypes(Attrs, AttributeSet::FunctionIndex, true, V); Assert1(!(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && @@ -801,7 +832,7 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, "Attributes 'noinline and alwaysinline' are incompatible!", V); } -static bool VerifyAttributeCount(const AttributeSet &Attrs, unsigned Params) { +bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { if (Attrs.getNumSlots() == 0) return true; @@ -837,7 +868,7 @@ void Verifier::visitFunction(Function &F) { Assert1(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(), "Invalid struct return type!", &F); - const AttributeSet &Attrs = F.getAttributes(); + AttributeSet Attrs = F.getAttributes(); Assert1(VerifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); @@ -1350,7 +1381,7 @@ void Verifier::VerifyCallSite(CallSite CS) { "Call parameter type does not match function signature!", CS.getArgument(i), FTy->getParamType(i), I); - const AttributeSet &Attrs = CS.getAttributes(); + AttributeSet Attrs = CS.getAttributes(); Assert1(VerifyAttributeCount(Attrs, CS.arg_size()), "Attribute after last parameter!", I); @@ -1358,15 +1389,41 @@ void Verifier::VerifyCallSite(CallSite CS) { // Verify call attributes. VerifyFunctionAttrs(FTy, Attrs, I); - if (FTy->isVarArg()) + if (FTy->isVarArg()) { + // FIXME? is 'nest' even legal here? + bool SawNest = false; + bool SawReturned = false; + + for (unsigned Idx = 1; Idx < 1 + FTy->getNumParams(); ++Idx) { + if (Attrs.hasAttribute(Idx, Attribute::Nest)) + SawNest = true; + if (Attrs.hasAttribute(Idx, Attribute::Returned)) + SawReturned = true; + } + // Check attributes on the varargs part. for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) { - VerifyParameterAttrs(Attrs, Idx, CS.getArgument(Idx-1)->getType(), - false, I); + 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; + } + + if (Attrs.hasAttribute(Idx, Attribute::Returned)) { + Assert1(!SawReturned, "More than one parameter has attribute returned!", + I); + Assert1(Ty->canLosslesslyBitCastTo(FTy->getReturnType()), + "Incompatible argument and return types for 'returned' " + "attribute", I); + SawReturned = true; + } Assert1(!Attrs.hasAttribute(Idx, Attribute::StructRet), "Attribute 'sret' cannot be used for vararg call arguments!", I); } + } // Verify that there's no metadata unless it's a direct call to an intrinsic. if (CS.getCalledFunction() == 0 || |