diff options
author | Stephen Hines <srhines@google.com> | 2014-12-01 14:51:49 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-12-02 16:08:10 -0800 |
commit | 37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch) | |
tree | 8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /lib/IR | |
parent | d2327b22152ced7bc46dc629fc908959e8a52d03 (diff) | |
download | external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2 external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip |
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'lib/IR')
46 files changed, 3084 insertions, 2300 deletions
diff --git a/lib/IR/Android.mk b/lib/IR/Android.mk index c51b241d1d..a3632cf06d 100644 --- a/lib/IR/Android.mk +++ b/lib/IR/Android.mk @@ -41,6 +41,7 @@ vmcore_SRC_FILES := \ Type.cpp \ TypeFinder.cpp \ Use.cpp \ + UseListOrder.cpp \ User.cpp \ Value.cpp \ ValueSymbolTable.cpp \ diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index a7499bc09b..1961a20901 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -49,6 +49,213 @@ AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} // Helper Functions //===----------------------------------------------------------------------===// +namespace { +struct OrderMap { + DenseMap<const Value *, std::pair<unsigned, bool>> IDs; + + unsigned size() const { return IDs.size(); } + std::pair<unsigned, bool> &operator[](const Value *V) { return IDs[V]; } + std::pair<unsigned, bool> lookup(const Value *V) const { + return IDs.lookup(V); + } + void index(const Value *V) { + // Explicitly sequence get-size and insert-value operations to avoid UB. + unsigned ID = IDs.size() + 1; + IDs[V].first = ID; + } +}; +} + +static void orderValue(const Value *V, OrderMap &OM) { + if (OM.lookup(V).first) + return; + + if (const Constant *C = dyn_cast<Constant>(V)) + if (C->getNumOperands() && !isa<GlobalValue>(C)) + for (const Value *Op : C->operands()) + if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op)) + orderValue(Op, OM); + + // Note: we cannot cache this lookup above, since inserting into the map + // changes the map's size, and thus affects the other IDs. + OM.index(V); +} + +static OrderMap orderModule(const Module *M) { + // This needs to match the order used by ValueEnumerator::ValueEnumerator() + // and ValueEnumerator::incorporateFunction(). + OrderMap OM; + + for (const GlobalVariable &G : M->globals()) { + if (G.hasInitializer()) + if (!isa<GlobalValue>(G.getInitializer())) + orderValue(G.getInitializer(), OM); + orderValue(&G, OM); + } + for (const GlobalAlias &A : M->aliases()) { + if (!isa<GlobalValue>(A.getAliasee())) + orderValue(A.getAliasee(), OM); + orderValue(&A, OM); + } + for (const Function &F : *M) { + if (F.hasPrefixData()) + if (!isa<GlobalValue>(F.getPrefixData())) + orderValue(F.getPrefixData(), OM); + orderValue(&F, OM); + + if (F.isDeclaration()) + continue; + + for (const Argument &A : F.args()) + orderValue(&A, OM); + for (const BasicBlock &BB : F) { + orderValue(&BB, OM); + for (const Instruction &I : BB) { + for (const Value *Op : I.operands()) + if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) || + isa<InlineAsm>(*Op)) + orderValue(Op, OM); + orderValue(&I, OM); + } + } + } + return OM; +} + +static void predictValueUseListOrderImpl(const Value *V, const Function *F, + unsigned ID, const OrderMap &OM, + UseListOrderStack &Stack) { + // Predict use-list order for this one. + typedef std::pair<const Use *, unsigned> Entry; + SmallVector<Entry, 64> List; + for (const Use &U : V->uses()) + // Check if this user will be serialized. + if (OM.lookup(U.getUser()).first) + List.push_back(std::make_pair(&U, List.size())); + + if (List.size() < 2) + // We may have lost some users. + return; + + bool GetsReversed = + !isa<GlobalVariable>(V) && !isa<Function>(V) && !isa<BasicBlock>(V); + if (auto *BA = dyn_cast<BlockAddress>(V)) + ID = OM.lookup(BA->getBasicBlock()).first; + std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) { + const Use *LU = L.first; + const Use *RU = R.first; + if (LU == RU) + return false; + + auto LID = OM.lookup(LU->getUser()).first; + auto RID = OM.lookup(RU->getUser()).first; + + // If ID is 4, then expect: 7 6 5 1 2 3. + if (LID < RID) { + if (GetsReversed) + if (RID <= ID) + return true; + return false; + } + if (RID < LID) { + if (GetsReversed) + if (LID <= ID) + return false; + return true; + } + + // LID and RID are equal, so we have different operands of the same user. + // Assume operands are added in order for all instructions. + if (GetsReversed) + if (LID <= ID) + return LU->getOperandNo() < RU->getOperandNo(); + return LU->getOperandNo() > RU->getOperandNo(); + }); + + if (std::is_sorted( + List.begin(), List.end(), + [](const Entry &L, const Entry &R) { return L.second < R.second; })) + // Order is already correct. + return; + + // Store the shuffle. + Stack.emplace_back(V, F, List.size()); + assert(List.size() == Stack.back().Shuffle.size() && "Wrong size"); + for (size_t I = 0, E = List.size(); I != E; ++I) + Stack.back().Shuffle[I] = List[I].second; +} + +static void predictValueUseListOrder(const Value *V, const Function *F, + OrderMap &OM, UseListOrderStack &Stack) { + auto &IDPair = OM[V]; + assert(IDPair.first && "Unmapped value"); + if (IDPair.second) + // Already predicted. + return; + + // Do the actual prediction. + IDPair.second = true; + if (!V->use_empty() && std::next(V->use_begin()) != V->use_end()) + predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack); + + // Recursive descent into constants. + if (const Constant *C = dyn_cast<Constant>(V)) + if (C->getNumOperands()) // Visit GlobalValues. + for (const Value *Op : C->operands()) + if (isa<Constant>(Op)) // Visit GlobalValues. + predictValueUseListOrder(Op, F, OM, Stack); +} + +static UseListOrderStack predictUseListOrder(const Module *M) { + OrderMap OM = orderModule(M); + + // Use-list orders need to be serialized after all the users have been added + // to a value, or else the shuffles will be incomplete. Store them per + // function in a stack. + // + // Aside from function order, the order of values doesn't matter much here. + UseListOrderStack Stack; + + // We want to visit the functions backward now so we can list function-local + // constants in the last Function they're used in. Module-level constants + // have already been visited above. + for (auto I = M->rbegin(), E = M->rend(); I != E; ++I) { + const Function &F = *I; + if (F.isDeclaration()) + continue; + for (const BasicBlock &BB : F) + predictValueUseListOrder(&BB, &F, OM, Stack); + for (const Argument &A : F.args()) + predictValueUseListOrder(&A, &F, OM, Stack); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + for (const Value *Op : I.operands()) + if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues. + predictValueUseListOrder(Op, &F, OM, Stack); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + predictValueUseListOrder(&I, &F, OM, Stack); + } + + // Visit globals last. + for (const GlobalVariable &G : M->globals()) + predictValueUseListOrder(&G, nullptr, OM, Stack); + for (const Function &F : *M) + predictValueUseListOrder(&F, nullptr, OM, Stack); + for (const GlobalAlias &A : M->aliases()) + predictValueUseListOrder(&A, nullptr, OM, Stack); + for (const GlobalVariable &G : M->globals()) + if (G.hasInitializer()) + predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack); + for (const GlobalAlias &A : M->aliases()) + predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack); + for (const Function &F : *M) + if (F.hasPrefixData()) + predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack); + + return Stack; +} + static const Module *getModuleFromVal(const Value *V) { if (const Argument *MA = dyn_cast<Argument>(V)) return MA->getParent() ? MA->getParent()->getParent() : nullptr; @@ -78,6 +285,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break; case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break; case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break; + case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break; case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break; case CallingConv::ARM_APCS: Out << "arm_apcscc"; break; case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break; @@ -347,6 +555,8 @@ public: FunctionProcessed = false; } + const Function *getFunction() const { return TheFunction; } + /// After calling incorporateFunction, use this method to remove the /// most recently incorporated function from the SlotTracker. This /// will reset the state of the machine back to just the module contents. @@ -508,7 +718,7 @@ void SlotTracker::processFunction() { ST_DEBUG("Inserting Instructions:\n"); - SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; + SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst; // Add all of the basic blocks and instructions with no names. for (Function::const_iterator BB = TheFunction->begin(), @@ -1279,6 +1489,9 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, void AssemblyWriter::printModule(const Module *M) { Machine.initialize(); + if (shouldPreserveAssemblyUseListOrder()) + UseListOrders = predictUseListOrder(M); + if (!M->getModuleIdentifier().empty() && // Don't print the ID if it will start a new line (which would // require a comment char before it). @@ -1339,9 +1552,13 @@ void AssemblyWriter::printModule(const Module *M) { I != E; ++I) printAlias(I); + // Output global use-lists. + printUseLists(nullptr); + // Output all of the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) printFunction(I); + assert(UseListOrders.empty() && "All use-lists should have been consumed"); // Output all attribute groups. if (!Machine.as_empty()) { @@ -1509,6 +1726,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { PrintLLVMName(Out, GA); Out << " = "; } + PrintLinkage(GA->getLinkage(), Out); PrintVisibility(GA->getVisibility(), Out); PrintDLLStorageClass(GA->getDLLStorageClass(), Out); PrintThreadLocalModel(GA->getThreadLocalMode(), Out); @@ -1517,8 +1735,6 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { Out << "alias "; - PrintLinkage(GA->getLinkage(), Out); - const Constant *Aliasee = GA->getAliasee(); if (!Aliasee) { @@ -1693,6 +1909,9 @@ void AssemblyWriter::printFunction(const Function *F) { for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I) printBasicBlock(I); + // Output the function's use-lists. + printUseLists(F); + Out << "}\n"; } @@ -1956,6 +2175,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ", "; writeParamOperand(CI->getArgOperand(op), PAL, op + 1); } + + // Emit an ellipsis if this is a musttail call in a vararg function. This + // is only to aid readability, musttail calls forward varargs by default. + if (CI->isMustTailCall() && CI->getParent() && + CI->getParent()->getParent() && + CI->getParent()->getParent()->isVarArg()) + Out << ", ..."; + Out << ')'; if (PAL.hasAttributes(AttributeSet::FunctionIndex)) Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); @@ -2088,7 +2315,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } // Print Metadata info. - SmallVector<std::pair<unsigned, MDNode*>, 4> InstMD; + SmallVector<std::pair<unsigned, MDNode *>, 4> InstMD; I.getAllMetadata(InstMD); if (!InstMD.empty()) { SmallVector<StringRef, 8> MDNames; @@ -2114,7 +2341,7 @@ static void WriteMDNodeComment(const MDNode *Node, return; Value *Op = Node->getOperand(0); - if (!Op || !isa<ConstantInt>(Op) || cast<ConstantInt>(Op)->getBitWidth() < 32) + if (!Op || !isa<MDString>(Op)) return; DIDescriptor Desc(Node); @@ -2170,6 +2397,45 @@ void AssemblyWriter::writeAllAttributeGroups() { } // namespace llvm +void AssemblyWriter::printUseListOrder(const UseListOrder &Order) { + bool IsInFunction = Machine.getFunction(); + if (IsInFunction) + Out << " "; + + Out << "uselistorder"; + if (const BasicBlock *BB = + IsInFunction ? nullptr : dyn_cast<BasicBlock>(Order.V)) { + Out << "_bb "; + writeOperand(BB->getParent(), false); + Out << ", "; + writeOperand(BB, false); + } else { + Out << " "; + writeOperand(Order.V, true); + } + Out << ", { "; + + assert(Order.Shuffle.size() >= 2 && "Shuffle too small"); + Out << Order.Shuffle[0]; + for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I) + Out << ", " << Order.Shuffle[I]; + Out << " }\n"; +} + +void AssemblyWriter::printUseLists(const Function *F) { + auto hasMore = + [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; }; + if (!hasMore()) + // Nothing to do. + return; + + Out << "\n; uselistorder directives\n"; + while (hasMore()) { + printUseListOrder(UseListOrders.back()); + UseListOrders.pop_back(); + } +} + //===----------------------------------------------------------------------===// // External Interface declarations //===----------------------------------------------------------------------===// @@ -2291,7 +2557,7 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) cons void Value::dump() const { print(dbgs()); dbgs() << '\n'; } // Type::dump - allow easy printing of Types from the debugger. -void Type::dump() const { print(dbgs()); } +void Type::dump() const { print(dbgs()); dbgs() << '\n'; } // Module::dump() - Allow printing of Modules from the debugger. void Module::dump() const { print(dbgs(), nullptr); } diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h index aef9c8a3e9..60da5ad335 100644 --- a/lib/IR/AsmWriter.h +++ b/lib/IR/AsmWriter.h @@ -12,14 +12,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_ASSEMBLYWRITER_H -#define LLVM_IR_ASSEMBLYWRITER_H +#ifndef LLVM_LIB_IR_ASMWRITER_H +#define LLVM_LIB_IR_ASMWRITER_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/TypeFinder.h" +#include "llvm/IR/UseListOrder.h" #include "llvm/Support/FormattedStream.h" namespace llvm { @@ -73,6 +74,7 @@ private: TypePrinting TypePrinter; AssemblyAnnotationWriter *AnnotationWriter; SetVector<const Comdat *> Comdats; + UseListOrderStack UseListOrders; public: /// Construct an AssemblyWriter with an external SlotTracker @@ -111,6 +113,9 @@ public: void printInstructionLine(const Instruction &I); void printInstruction(const Instruction &I); + void printUseListOrder(const UseListOrder &Order); + void printUseLists(const Function *F); + private: void init(); @@ -121,4 +126,4 @@ private: } // namespace llvm -#endif //LLVM_IR_ASMWRITER_H +#endif diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index 9f3fd3e606..0448dc1740 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ATTRIBUTESIMPL_H -#define LLVM_ATTRIBUTESIMPL_H +#ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H +#define LLVM_LIB_IR_ATTRIBUTEIMPL_H #include "llvm/ADT/FoldingSet.h" #include "llvm/IR/Attributes.h" @@ -39,7 +39,7 @@ class AttributeImpl : public FoldingSetNode { protected: enum AttrEntryKind { EnumAttrEntry, - AlignAttrEntry, + IntAttrEntry, StringAttrEntry }; @@ -49,7 +49,7 @@ public: virtual ~AttributeImpl(); bool isEnumAttribute() const { return KindID == EnumAttrEntry; } - bool isAlignAttribute() const { return KindID == AlignAttrEntry; } + bool isIntAttribute() const { return KindID == IntAttrEntry; } bool isStringAttribute() const { return KindID == StringAttrEntry; } bool hasAttribute(Attribute::AttrKind A) const; @@ -67,7 +67,7 @@ public: void Profile(FoldingSetNodeID &ID) const { if (isEnumAttribute()) Profile(ID, getKindAsEnum(), 0); - else if (isAlignAttribute()) + else if (isIntAttribute()) Profile(ID, getKindAsEnum(), getValueAsInt()); else Profile(ID, getKindAsString(), getValueAsString()); @@ -108,19 +108,20 @@ public: Attribute::AttrKind getEnumKind() const { return Kind; } }; -class AlignAttributeImpl : public EnumAttributeImpl { +class IntAttributeImpl : public EnumAttributeImpl { void anchor() override; - unsigned Align; + uint64_t Val; public: - AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align) - : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) { + IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) + : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { assert( - (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) && - "Wrong kind for alignment attribute!"); + (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || + Kind == Attribute::Dereferenceable) && + "Wrong kind for int attribute!"); } - unsigned getAlignment() const { return Align; } + uint64_t getValue() const { return Val; } }; class StringAttributeImpl : public AttributeImpl { @@ -164,6 +165,7 @@ public: unsigned getAlignment() const; unsigned getStackAlignment() const; + uint64_t getDereferenceableBytes() const; std::string getAsString(bool InAttrGrp) const; typedef const Attribute *iterator; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 48a2ce858a..04545ea919 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -47,7 +47,7 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, if (!Val) PA = new EnumAttributeImpl(Kind); else - PA = new AlignAttributeImpl(Kind, Val); + PA = new IntAttributeImpl(Kind, Val); pImpl->AttrsSet.InsertNode(PA, InsertPoint); } @@ -88,6 +88,12 @@ Attribute Attribute::getWithStackAlignment(LLVMContext &Context, return get(Context, StackAlignment, Align); } +Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context, + uint64_t Bytes) { + assert(Bytes && "Bytes must be non-zero."); + return get(Context, Dereferenceable, Bytes); +} + //===----------------------------------------------------------------------===// // Attribute Accessor Methods //===----------------------------------------------------------------------===// @@ -96,8 +102,8 @@ bool Attribute::isEnumAttribute() const { return pImpl && pImpl->isEnumAttribute(); } -bool Attribute::isAlignAttribute() const { - return pImpl && pImpl->isAlignAttribute(); +bool Attribute::isIntAttribute() const { + return pImpl && pImpl->isIntAttribute(); } bool Attribute::isStringAttribute() const { @@ -106,15 +112,15 @@ bool Attribute::isStringAttribute() const { Attribute::AttrKind Attribute::getKindAsEnum() const { if (!pImpl) return None; - assert((isEnumAttribute() || isAlignAttribute()) && + assert((isEnumAttribute() || isIntAttribute()) && "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!"); + assert(isIntAttribute() && + "Expected the attribute to be an integer attribute!"); return pImpl ? pImpl->getValueAsInt() : 0; } @@ -156,6 +162,14 @@ unsigned Attribute::getStackAlignment() const { return pImpl->getValueAsInt(); } +/// This returns the number of dereferenceable bytes. +uint64_t Attribute::getDereferenceableBytes() const { + assert(hasAttribute(Attribute::Dereferenceable) && + "Trying to get dereferenceable bytes from " + "non-dereferenceable attribute!"); + return pImpl->getValueAsInt(); +} + std::string Attribute::getAsString(bool InAttrGrp) const { if (!pImpl) return ""; @@ -263,6 +277,20 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return Result; } + if (hasAttribute(Attribute::Dereferenceable)) { + std::string Result; + Result += "dereferenceable"; + if (InAttrGrp) { + Result += "="; + Result += utostr(getValueAsInt()); + } else { + Result += "("; + Result += utostr(getValueAsInt()); + Result += ")"; + } + return Result; + } + // Convert target-dependent attributes to strings of the form: // // "kind" @@ -296,7 +324,7 @@ bool Attribute::operator<(Attribute A) const { // Pin the vtables to this file. AttributeImpl::~AttributeImpl() {} void EnumAttributeImpl::anchor() {} -void AlignAttributeImpl::anchor() {} +void IntAttributeImpl::anchor() {} void StringAttributeImpl::anchor() {} bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { @@ -310,13 +338,13 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const { } Attribute::AttrKind AttributeImpl::getKindAsEnum() const { - assert(isEnumAttribute() || isAlignAttribute()); + assert(isEnumAttribute() || isIntAttribute()); return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); } uint64_t AttributeImpl::getValueAsInt() const { - assert(isAlignAttribute()); - return static_cast<const AlignAttributeImpl *>(this)->getAlignment(); + assert(isIntAttribute()); + return static_cast<const IntAttributeImpl *>(this)->getValue(); } StringRef AttributeImpl::getKindAsString() const { @@ -334,18 +362,18 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const { // relative to their enum value) and then strings. if (isEnumAttribute()) { if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); - if (AI.isAlignAttribute()) return true; + if (AI.isIntAttribute()) return true; if (AI.isStringAttribute()) return true; } - if (isAlignAttribute()) { + if (isIntAttribute()) { if (AI.isEnumAttribute()) return false; - if (AI.isAlignAttribute()) return getValueAsInt() < AI.getValueAsInt(); + if (AI.isIntAttribute()) return getValueAsInt() < AI.getValueAsInt(); if (AI.isStringAttribute()) return true; } if (AI.isEnumAttribute()) return false; - if (AI.isAlignAttribute()) return false; + if (AI.isIntAttribute()) return false; if (getKindAsString() == AI.getKindAsString()) return getValueAsString() < AI.getValueAsString(); return getKindAsString() < AI.getKindAsString(); @@ -398,6 +426,8 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::InAlloca: return 1ULL << 43; case Attribute::NonNull: return 1ULL << 44; case Attribute::JumpTable: return 1ULL << 45; + case Attribute::Dereferenceable: + llvm_unreachable("dereferenceable attribute not supported in raw format"); } llvm_unreachable("Unsupported attribute type"); } @@ -482,6 +512,13 @@ unsigned AttributeSetNode::getStackAlignment() const { return 0; } +uint64_t AttributeSetNode::getDereferenceableBytes() const { + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->hasAttribute(Attribute::Dereferenceable)) + return I->getDereferenceableBytes(); + return 0; +} + std::string AttributeSetNode::getAsString(bool InAttrGrp) const { std::string Str; for (iterator I = begin(), E = end(); I != E; ++I) { @@ -515,6 +552,8 @@ uint64_t AttributeSetImpl::Raw(unsigned Index) const { Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16; else if (Kind == Attribute::StackAlignment) Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26; + else if (Kind == Attribute::Dereferenceable) + llvm_unreachable("dereferenceable not supported in bit mask"); else Mask |= AttributeImpl::getAttrMask(Kind); } @@ -620,6 +659,10 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, else if (Kind == Attribute::StackAlignment) Attrs.push_back(std::make_pair(Index, Attribute:: getWithStackAlignment(C, B.getStackAlignment()))); + else if (Kind == Attribute::Dereferenceable) + Attrs.push_back(std::make_pair(Index, + Attribute::getWithDereferenceableBytes(C, + B.getDereferenceableBytes()))); else Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind))); } @@ -877,6 +920,11 @@ unsigned AttributeSet::getStackAlignment(unsigned Index) const { return ASN ? ASN->getStackAlignment() : 0; } +uint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getDereferenceableBytes() : 0; +} + std::string AttributeSet::getAsString(unsigned Index, bool InAttrGrp) const { AttributeSetNode *ASN = getAttributes(Index); @@ -956,7 +1004,7 @@ void AttributeSet::dump() const { //===----------------------------------------------------------------------===// AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) - : Attrs(0), Alignment(0), StackAlignment(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { AttributeSetImpl *pImpl = AS.pImpl; if (!pImpl) return; @@ -973,13 +1021,14 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) void AttrBuilder::clear() { Attrs.reset(); - Alignment = StackAlignment = 0; + Alignment = StackAlignment = DerefBytes = 0; } AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment && - "Adding alignment attribute without adding alignment value!"); + Val != Attribute::Dereferenceable && + "Adding integer attribute without adding a value!"); Attrs[Val] = true; return *this; } @@ -997,6 +1046,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { Alignment = Attr.getAlignment(); else if (Kind == Attribute::StackAlignment) StackAlignment = Attr.getStackAlignment(); + else if (Kind == Attribute::Dereferenceable) + DerefBytes = Attr.getDereferenceableBytes(); return *this; } @@ -1013,6 +1064,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { Alignment = 0; else if (Val == Attribute::StackAlignment) StackAlignment = 0; + else if (Val == Attribute::Dereferenceable) + DerefBytes = 0; return *this; } @@ -1029,7 +1082,7 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) { for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { Attribute Attr = *I; - if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { + if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { Attribute::AttrKind Kind = I->getKindAsEnum(); Attrs[Kind] = false; @@ -1037,6 +1090,8 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) { Alignment = 0; else if (Kind == Attribute::StackAlignment) StackAlignment = 0; + else if (Kind == Attribute::Dereferenceable) + DerefBytes = 0; } else { assert(Attr.isStringAttribute() && "Invalid attribute type!"); std::map<std::string, std::string>::iterator @@ -1079,6 +1134,14 @@ AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { return *this; } +AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) { + if (Bytes == 0) return *this; + + Attrs[Attribute::Dereferenceable] = true; + DerefBytes = Bytes; + return *this; +} + AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { // FIXME: What if both have alignments, but they don't match?! if (!Alignment) @@ -1087,6 +1150,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { if (!StackAlignment) StackAlignment = B.StackAlignment; + if (!DerefBytes) + DerefBytes = B.DerefBytes; + Attrs |= B.Attrs; for (td_const_iterator I = B.TargetDepAttrs.begin(), @@ -1117,7 +1183,7 @@ bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const { for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { Attribute Attr = *I; - if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { + if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { if (Attrs[I->getKindAsEnum()]) return true; } else { @@ -1142,7 +1208,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) { if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end()) return false; - return Alignment == B.Alignment && StackAlignment == B.StackAlignment; + return Alignment == B.Alignment && StackAlignment == B.StackAlignment && + DerefBytes == B.DerefBytes; } AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { @@ -1151,6 +1218,8 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; I = Attribute::AttrKind(I + 1)) { + if (I == Attribute::Dereferenceable) + continue; if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) { Attrs[I] = true; @@ -1184,6 +1253,7 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { .addAttribute(Attribute::NoAlias) .addAttribute(Attribute::NoCapture) .addAttribute(Attribute::NonNull) + .addDereferenceableAttr(1) // the int here is ignored .addAttribute(Attribute::ReadNone) .addAttribute(Attribute::ReadOnly) .addAttribute(Attribute::StructRet) diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp index 6554b3c5da..c24dfead43 100644 --- a/lib/IR/AutoUpgrade.cpp +++ b/lib/IR/AutoUpgrade.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" @@ -43,6 +44,22 @@ static bool UpgradeSSE41Function(Function* F, Intrinsic::ID IID, return true; } +// Upgrade the declarations of intrinsic functions whose 8-bit immediate mask +// arguments have changed their type from i32 to i8. +static bool UpgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID, + Function *&NewFn) { + // Check that the last argument is an i32. + Type *LastArgType = F->getFunctionType()->getParamType( + F->getFunctionType()->getNumParams() - 1); + if (!LastArgType->isIntegerTy(32)) + return false; + + // Move this function aside and map down. + F->setName(F->getName() + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), IID); + return true; +} + static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { assert(F && "Illegal to upgrade a non-existent Function."); @@ -90,6 +107,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { } break; } + case 'd': { + if (Name.startswith("dbg.declare") && F->arg_size() == 2) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_declare); + return true; + } + if (Name.startswith("dbg.value") && F->arg_size() == 3) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value); + return true; + } + break; + } + case 'o': // We only need to change the name to match the mangling including the // address space. @@ -130,6 +161,51 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { if (Name == "x86.sse41.ptestnzc") return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestnzc, NewFn); } + // Several blend and other instructions with maskes used the wrong number of + // bits. + if (Name == "x86.sse41.pblendw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_pblendw, + NewFn); + if (Name == "x86.sse41.blendpd") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendpd, + NewFn); + if (Name == "x86.sse41.blendps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendps, + NewFn); + if (Name == "x86.sse41.insertps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_insertps, + NewFn); + if (Name == "x86.sse41.dppd") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dppd, + NewFn); + if (Name == "x86.sse41.dpps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dpps, + NewFn); + if (Name == "x86.sse41.mpsadbw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_mpsadbw, + NewFn); + if (Name == "x86.avx.blend.pd.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx_blend_pd_256, NewFn); + if (Name == "x86.avx.blend.ps.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx_blend_ps_256, NewFn); + if (Name == "x86.avx.dp.ps.256") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx_dp_ps_256, + NewFn); + if (Name == "x86.avx2.pblendw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_pblendw, + NewFn); + if (Name == "x86.avx2.pblendd.128") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx2_pblendd_128, NewFn); + if (Name == "x86.avx2.pblendd.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx2_pblendd_256, NewFn); + if (Name == "x86.avx2.mpsadbw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_mpsadbw, + NewFn); + // frcz.ss/sd may need to have an argument dropped if (Name.startswith("x86.xop.vfrcz.ss") && F->arg_size() == 2) { F->setName(Name + ".old"); @@ -173,66 +249,27 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) { return Upgraded; } -static bool UpgradeGlobalStructors(GlobalVariable *GV) { - ArrayType *ATy = dyn_cast<ArrayType>(GV->getType()->getElementType()); - StructType *OldTy = - ATy ? dyn_cast<StructType>(ATy->getElementType()) : nullptr; - - // Only upgrade an array of a two field struct with the appropriate field - // types. - if (!OldTy || OldTy->getNumElements() != 2) - return false; - - // Get the upgraded 3 element type. - PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo(); - Type *Tys[3] = { - OldTy->getElementType(0), - OldTy->getElementType(1), - VoidPtrTy - }; - StructType *NewTy = - StructType::get(GV->getContext(), Tys, /*isPacked=*/false); - - // Build new constants with a null third field filled in. - Constant *OldInitC = GV->getInitializer(); - ConstantArray *OldInit = dyn_cast<ConstantArray>(OldInitC); - if (!OldInit && !isa<ConstantAggregateZero>(OldInitC)) - return false; - std::vector<Constant *> Initializers; - if (OldInit) { - for (Use &U : OldInit->operands()) { - ConstantStruct *Init = cast<ConstantStruct>(&U); - Constant *NewInit = - ConstantStruct::get(NewTy, Init->getOperand(0), Init->getOperand(1), - Constant::getNullValue(VoidPtrTy), nullptr); - Initializers.push_back(NewInit); - } - } - assert(Initializers.size() == ATy->getNumElements()); - - // Replace the old GV with a new one. - ATy = ArrayType::get(NewTy, Initializers.size()); - Constant *NewInit = ConstantArray::get(ATy, Initializers); - GlobalVariable *NewGV = new GlobalVariable( - *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "", - GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(), - GV->isExternallyInitialized()); - NewGV->copyAttributesFrom(GV); - NewGV->takeName(GV); - assert(GV->use_empty() && "program cannot use initializer list"); - GV->eraseFromParent(); - return true; -} - bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { - if (GV->getName() == "llvm.global_ctors" || - GV->getName() == "llvm.global_dtors") - return UpgradeGlobalStructors(GV); - // Nothing to do yet. return false; } +static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { + if (!DbgNode || Elt >= DbgNode->getNumOperands()) + return nullptr; + return dyn_cast_or_null<MDNode>(DbgNode->getOperand(Elt)); +} + +static DIExpression getExpression(Value *VarOperand, Function *F) { + // Old-style DIVariables have an optional expression as the 8th element. + DIExpression Expr(getNodeField(cast<MDNode>(VarOperand), 8)); + if (!Expr) { + DIBuilder DIB(*F->getParent()); + Expr = DIB.createExpression(); + } + return Expr; +} + // UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the // upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. @@ -396,12 +433,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { } std::string Name = CI->getName().str(); - CI->setName(Name + ".old"); + if (!Name.empty()) + CI->setName(Name + ".old"); switch (NewFn->getIntrinsicID()) { default: llvm_unreachable("Unknown function for CallInst upgrade."); + // Upgrade debug intrinsics to use an additional DIExpression argument. + case Intrinsic::dbg_declare: { + auto NewCI = + Builder.CreateCall3(NewFn, CI->getArgOperand(0), CI->getArgOperand(1), + getExpression(CI->getArgOperand(1), F), Name); + NewCI->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + return; + } + case Intrinsic::dbg_value: { + auto NewCI = Builder.CreateCall4( + NewFn, CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), + getExpression(CI->getArgOperand(2), F), Name); + NewCI->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + return; + } case Intrinsic::ctlz: case Intrinsic::cttz: assert(CI->getNumArgOperands() == 1 && @@ -419,14 +476,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); return; - case Intrinsic::arm_neon_vclz: { - // Change name from llvm.arm.neon.vclz.* to llvm.ctlz.* - CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), - Builder.getFalse(), - "llvm.ctlz." + Name.substr(14))); - CI->eraseFromParent(); - return; - } case Intrinsic::ctpop: { CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0))); CI->eraseFromParent(); @@ -468,6 +517,34 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); return; } + + case Intrinsic::x86_sse41_pblendw: + case Intrinsic::x86_sse41_blendpd: + case Intrinsic::x86_sse41_blendps: + case Intrinsic::x86_sse41_insertps: + case Intrinsic::x86_sse41_dppd: + case Intrinsic::x86_sse41_dpps: + case Intrinsic::x86_sse41_mpsadbw: + case Intrinsic::x86_avx_blend_pd_256: + case Intrinsic::x86_avx_blend_ps_256: + case Intrinsic::x86_avx_dp_ps_256: + case Intrinsic::x86_avx2_pblendw: + case Intrinsic::x86_avx2_pblendd_128: + case Intrinsic::x86_avx2_pblendd_256: + case Intrinsic::x86_avx2_mpsadbw: { + // Need to truncate the last argument from i32 to i8 -- this argument models + // an inherently 8-bit immediate operand to these x86 instructions. + SmallVector<Value *, 4> Args(CI->arg_operands().begin(), + CI->arg_operands().end()); + + // Replace the last argument with a trunc. + Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc"); + + CallInst *NewCall = Builder.CreateCall(NewFn, Args); + CI->replaceAllUsesWith(NewCall); + CI->eraseFromParent(); + return; + } } } @@ -580,7 +657,9 @@ bool llvm::UpgradeDebugInfo(Module &M) { void llvm::UpgradeMDStringConstant(std::string &String) { const std::string OldPrefix = "llvm.vectorizer."; - if (String.find(OldPrefix) == 0) { - String.replace(0, OldPrefix.size(), "llvm.loop.vectorize."); + if (String == "llvm.vectorizer.unroll") { + String = "llvm.loop.interleave.count"; + } else if (String.find(OldPrefix) == 0) { + String.replace(0, OldPrefix.size(), "llvm.loop.vectorize."); } } diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp index ba07433103..5ed9bed1ba 100644 --- a/lib/IR/BasicBlock.cpp +++ b/lib/IR/BasicBlock.cpp @@ -50,17 +50,24 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, // Make sure that we get added to a function LeakDetector::addGarbageObject(this); - if (InsertBefore) { - assert(NewParent && + if (NewParent) + insertInto(NewParent, InsertBefore); + else + assert(!InsertBefore && "Cannot insert block before another block with no function!"); - NewParent->getBasicBlockList().insert(InsertBefore, this); - } else if (NewParent) { - NewParent->getBasicBlockList().push_back(this); - } setName(Name); } +void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) { + assert(NewParent && "Expected a parent"); + assert(!Parent && "Already has a parent"); + + if (InsertBefore) + NewParent->getBasicBlockList().insert(InsertBefore, this); + else + NewParent->getBasicBlockList().push_back(this); +} BasicBlock::~BasicBlock() { // If the address of the block is taken and it is being deleted (e.g. because @@ -131,6 +138,37 @@ const TerminatorInst *BasicBlock::getTerminator() const { return dyn_cast<TerminatorInst>(&InstList.back()); } +CallInst *BasicBlock::getTerminatingMustTailCall() { + if (InstList.empty()) + return nullptr; + ReturnInst *RI = dyn_cast<ReturnInst>(&InstList.back()); + if (!RI || RI == &InstList.front()) + return nullptr; + + Instruction *Prev = RI->getPrevNode(); + if (!Prev) + return nullptr; + + if (Value *RV = RI->getReturnValue()) { + if (RV != Prev) + return nullptr; + + // Look through the optional bitcast. + if (auto *BI = dyn_cast<BitCastInst>(Prev)) { + RV = BI->getOperand(0); + Prev = BI->getPrevNode(); + if (!Prev || RV != Prev) + return nullptr; + } + } + + if (auto *CI = dyn_cast<CallInst>(Prev)) { + if (CI->isMustTailCall()) + return CI; + } + return nullptr; +} + Instruction* BasicBlock::getFirstNonPHI() { BasicBlock::iterator i = begin(); // All valid basic blocks should have a terminator, diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt index 38a80b18bd..b3889e6fdf 100644 --- a/lib/IR/CMakeLists.txt +++ b/lib/IR/CMakeLists.txt @@ -39,6 +39,7 @@ add_llvm_library(LLVMCore Type.cpp TypeFinder.cpp Use.cpp + UseListOrder.cpp User.cpp Value.cpp ValueSymbolTable.cpp diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 395ac3907b..cdfb41f7dc 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -593,8 +593,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, bool ignored; uint64_t x[2]; uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth(); - (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, - APFloat::rmTowardZero, &ignored); + if (APFloat::opInvalidOp == + V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, + APFloat::rmTowardZero, &ignored)) { + // Undefined behavior invoked - the destination type can't represent + // the input constant. + return UndefValue::get(DestTy); + } APInt Val(DestBitWidth, x); return ConstantInt::get(FPC->getContext(), Val); } @@ -653,9 +658,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, APInt api = CI->getValue(); APFloat apf(DestTy->getFltSemantics(), APInt::getNullValue(DestTy->getPrimitiveSizeInBits())); - (void)apf.convertFromAPInt(api, - opc==Instruction::SIToFP, - APFloat::rmNearestTiesToEven); + if (APFloat::opOverflow & + apf.convertFromAPInt(api, opc==Instruction::SIToFP, + APFloat::rmNearestTiesToEven)) { + // Undefined behavior invoked - the destination type can't represent + // the input constant. + return UndefValue::get(DestTy); + } return ConstantFP::get(V->getContext(), apf); } return nullptr; @@ -674,6 +683,9 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, } return nullptr; case Instruction::Trunc: { + if (V->getType()->isVectorTy()) + return nullptr; + uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth(); if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { return ConstantInt::get(V->getContext(), @@ -2144,9 +2156,10 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, // If all indices are known integers and normalized, we can do a simple // check for the "inbounds" property. - if (!Unknown && !inBounds && - isa<GlobalVariable>(C) && isInBoundsIndices(Idxs)) - return ConstantExpr::getInBoundsGetElementPtr(C, Idxs); + if (!Unknown && !inBounds) + if (auto *GV = dyn_cast<GlobalVariable>(C)) + if (!GV->hasExternalWeakLinkage() && isInBoundsIndices(Idxs)) + return ConstantExpr::getInBoundsGetElementPtr(C, Idxs); return nullptr; } diff --git a/lib/IR/ConstantFold.h b/lib/IR/ConstantFold.h index e12f27a7cb..a516abe024 100644 --- a/lib/IR/ConstantFold.h +++ b/lib/IR/ConstantFold.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CONSTANTFOLDING_H -#define CONSTANTFOLDING_H +#ifndef LLVM_LIB_IR_CONSTANTFOLD_H +#define LLVM_LIB_IR_CONSTANTFOLD_H #include "llvm/ADT/ArrayRef.h" diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index b815936ac4..e0cb835c2c 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -107,6 +107,28 @@ bool Constant::isAllOnesValue() const { return false; } +bool Constant::isOneValue() const { + // Check for 1 integers + if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) + return CI->isOne(); + + // Check for FP which are bitcasted from 1 integers + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) + return CFP->getValueAPF().bitcastToAPInt() == 1; + + // Check for constant vectors which are splats of 1 values. + if (const ConstantVector *CV = dyn_cast<ConstantVector>(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isOneValue(); + + // Check for constant vectors which are splats of 1 values. + if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isOneValue(); + + return false; +} + bool Constant::isMinSignedValue() const { // Check for INT_MIN integers if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) @@ -129,6 +151,29 @@ bool Constant::isMinSignedValue() const { return false; } +bool Constant::isNotMinSignedValue() const { + // Check for INT_MIN integers + if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) + return !CI->isMinValue(/*isSigned=*/true); + + // Check for FP which are bitcasted from INT_MIN integers + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) + return !CFP->getValueAPF().bitcastToAPInt().isMinSignedValue(); + + // Check for constant vectors which are splats of INT_MIN values. + if (const ConstantVector *CV = dyn_cast<ConstantVector>(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isNotMinSignedValue(); + + // Check for constant vectors which are splats of INT_MIN values. + if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isNotMinSignedValue(); + + // It *may* contain INT_MIN, we can't tell. + return false; +} + // Constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(Type *Ty) { switch (Ty->getTypeID()) { @@ -261,7 +306,7 @@ void Constant::destroyConstantImpl() { } static bool canTrapImpl(const Constant *C, - SmallPtrSet<const ConstantExpr *, 4> &NonTrappingOps) { + SmallPtrSetImpl<const ConstantExpr *> &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>(C); @@ -271,7 +316,7 @@ static bool canTrapImpl(const Constant *C, // ConstantExpr traps if any operands can trap. 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)) + if (NonTrappingOps.insert(Op).second && canTrapImpl(Op, NonTrappingOps)) return true; } } @@ -318,7 +363,7 @@ ConstHasGlobalValuePredicate(const Constant *C, const Constant *ConstOp = dyn_cast<Constant>(Op); if (!ConstOp) continue; - if (Visited.insert(ConstOp)) + if (Visited.insert(ConstOp).second) WorkList.push_back(ConstOp); } } @@ -781,6 +826,11 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V) } Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { + if (Constant *C = getImpl(Ty, V)) + return C; + return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V); +} +Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) { // Empty arrays are canonicalized to ConstantAggregateZero. if (V.empty()) return ConstantAggregateZero::get(Ty); @@ -789,7 +839,6 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { assert(V[i]->getType() == Ty->getElementType() && "Wrong type in array element initializer"); } - LLVMContextImpl *pImpl = Ty->getContext().pImpl; // If this is an all-zero array, return a ConstantAggregateZero object. If // all undef, return an UndefValue, if "all simple", then return a @@ -871,7 +920,7 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { } // Otherwise, we really do want to create a ConstantArray. - return pImpl->ArrayConstants.getOrCreate(Ty, V); + return nullptr; } /// getTypeForElements - Return an anonymous struct type to use for a constant @@ -959,9 +1008,14 @@ ConstantVector::ConstantVector(VectorType *T, ArrayRef<Constant *> V) // ConstantVector accessors. Constant *ConstantVector::get(ArrayRef<Constant*> V) { + if (Constant *C = getImpl(V)) + return C; + VectorType *Ty = VectorType::get(V.front()->getType(), V.size()); + return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V); +} +Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) { assert(!V.empty() && "Vectors can't be empty"); VectorType *T = VectorType::get(V.front()->getType(), V.size()); - LLVMContextImpl *pImpl = T->getContext().pImpl; // If this is an all-undef or all-zero vector, return a // ConstantAggregateZero or UndefValue. @@ -1053,7 +1107,7 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) { // Otherwise, the element type isn't compatible with ConstantDataVector, or // the operand list constants a ConstantExpr or something else strange. - return pImpl->VectorConstants.getOrCreate(T, V); + return nullptr; } Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) { @@ -1141,8 +1195,8 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { /// getWithOperands - This returns the current constant expression with the /// operands replaced with the specified values. The specified array must /// have the same number of operands as our current one. -Constant *ConstantExpr:: -getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const { +Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, + bool OnlyIfReduced) const { assert(Ops.size() == getNumOperands() && "Operand count mismatch!"); bool AnyChange = Ty != getType(); for (unsigned i = 0; i != Ops.size(); ++i) @@ -1151,6 +1205,7 @@ getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const { if (!AnyChange) // No operands changed, return self. return const_cast<ConstantExpr*>(this); + Type *OnlyIfReducedTy = OnlyIfReduced ? Ty : nullptr; switch (getOpcode()) { case Instruction::Trunc: case Instruction::ZExt: @@ -1165,28 +1220,34 @@ getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const { case Instruction::IntToPtr: case Instruction::BitCast: case Instruction::AddrSpaceCast: - return ConstantExpr::getCast(getOpcode(), Ops[0], Ty); + return ConstantExpr::getCast(getOpcode(), Ops[0], Ty, OnlyIfReduced); case Instruction::Select: - return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); + return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2], OnlyIfReducedTy); case Instruction::InsertElement: - return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); + return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2], + OnlyIfReducedTy); case Instruction::ExtractElement: - return ConstantExpr::getExtractElement(Ops[0], Ops[1]); + return ConstantExpr::getExtractElement(Ops[0], Ops[1], OnlyIfReducedTy); case Instruction::InsertValue: - return ConstantExpr::getInsertValue(Ops[0], Ops[1], getIndices()); + return ConstantExpr::getInsertValue(Ops[0], Ops[1], getIndices(), + OnlyIfReducedTy); case Instruction::ExtractValue: - return ConstantExpr::getExtractValue(Ops[0], getIndices()); + return ConstantExpr::getExtractValue(Ops[0], getIndices(), OnlyIfReducedTy); case Instruction::ShuffleVector: - return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); + return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2], + OnlyIfReducedTy); case Instruction::GetElementPtr: return ConstantExpr::getGetElementPtr(Ops[0], Ops.slice(1), - cast<GEPOperator>(this)->isInBounds()); + cast<GEPOperator>(this)->isInBounds(), + OnlyIfReducedTy); case Instruction::ICmp: case Instruction::FCmp: - return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]); + return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1], + OnlyIfReducedTy); default: assert(getNumOperands() == 2 && "Must be binary operator?"); - return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassOptionalData); + return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassOptionalData, + OnlyIfReducedTy); } } @@ -1447,27 +1508,21 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { // and return early. BlockAddress *&NewBA = getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)]; - if (!NewBA) { - getBasicBlock()->AdjustBlockAddressRefCount(-1); - - // Remove the old entry, this can't cause the map to rehash (just a - // tombstone will get added). - getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), - getBasicBlock())); - NewBA = this; - setOperand(0, NewF); - setOperand(1, NewBB); - getBasicBlock()->AdjustBlockAddressRefCount(1); + if (NewBA) { + replaceUsesOfWithOnConstantImpl(NewBA); return; } - // Otherwise, I do need to replace this with an existing value. - assert(NewBA != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(NewBA); + getBasicBlock()->AdjustBlockAddressRefCount(-1); - destroyConstant(); + // Remove the old entry, this can't cause the map to rehash (just a + // tombstone will get added). + getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), + getBasicBlock())); + NewBA = this; + setOperand(0, NewF); + setOperand(1, NewBB); + getBasicBlock()->AdjustBlockAddressRefCount(1); } //---- ConstantExpr::get() implementations. @@ -1475,22 +1530,26 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { /// This is a utility function to handle folding of casts and lookup of the /// cast in the ExprConstants map. It is used by the various get* methods below. -static inline Constant *getFoldedCast( - Instruction::CastOps opc, Constant *C, Type *Ty) { +static Constant *getFoldedCast(Instruction::CastOps opc, Constant *C, Type *Ty, + bool OnlyIfReduced = false) { assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!"); // Fold a few common cases if (Constant *FC = ConstantFoldCastInstruction(opc, C, Ty)) return FC; + if (OnlyIfReduced) + return nullptr; + LLVMContextImpl *pImpl = Ty->getContext().pImpl; // Look up the constant in the table first to ensure uniqueness. - ExprMapKeyType Key(opc, C); + ConstantExprKeyType Key(opc, C); return pImpl->ExprConstants.getOrCreate(Ty, Key); } -Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) { +Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty, + bool OnlyIfReduced) { Instruction::CastOps opc = Instruction::CastOps(oc); assert(Instruction::isCast(opc) && "opcode out of range"); assert(C && Ty && "Null arguments to getCast"); @@ -1499,19 +1558,32 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) { switch (opc) { default: llvm_unreachable("Invalid cast opcode"); - case Instruction::Trunc: return getTrunc(C, Ty); - case Instruction::ZExt: return getZExt(C, Ty); - case Instruction::SExt: return getSExt(C, Ty); - case Instruction::FPTrunc: return getFPTrunc(C, Ty); - case Instruction::FPExt: return getFPExtend(C, Ty); - case Instruction::UIToFP: return getUIToFP(C, Ty); - case Instruction::SIToFP: return getSIToFP(C, Ty); - case Instruction::FPToUI: return getFPToUI(C, Ty); - case Instruction::FPToSI: return getFPToSI(C, Ty); - case Instruction::PtrToInt: return getPtrToInt(C, Ty); - case Instruction::IntToPtr: return getIntToPtr(C, Ty); - case Instruction::BitCast: return getBitCast(C, Ty); - case Instruction::AddrSpaceCast: return getAddrSpaceCast(C, Ty); + case Instruction::Trunc: + return getTrunc(C, Ty, OnlyIfReduced); + case Instruction::ZExt: + return getZExt(C, Ty, OnlyIfReduced); + case Instruction::SExt: + return getSExt(C, Ty, OnlyIfReduced); + case Instruction::FPTrunc: + return getFPTrunc(C, Ty, OnlyIfReduced); + case Instruction::FPExt: + return getFPExtend(C, Ty, OnlyIfReduced); + case Instruction::UIToFP: + return getUIToFP(C, Ty, OnlyIfReduced); + case Instruction::SIToFP: + return getSIToFP(C, Ty, OnlyIfReduced); + case Instruction::FPToUI: + return getFPToUI(C, Ty, OnlyIfReduced); + case Instruction::FPToSI: + return getFPToSI(C, Ty, OnlyIfReduced); + case Instruction::PtrToInt: + return getPtrToInt(C, Ty, OnlyIfReduced); + case Instruction::IntToPtr: + return getIntToPtr(C, Ty, OnlyIfReduced); + case Instruction::BitCast: + return getBitCast(C, Ty, OnlyIfReduced); + case Instruction::AddrSpaceCast: + return getAddrSpaceCast(C, Ty, OnlyIfReduced); } } @@ -1584,7 +1656,7 @@ Constant *ConstantExpr::getFPCast(Constant *C, Type *Ty) { return getCast(opcode, C, Ty); } -Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) { +Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1595,10 +1667,10 @@ Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) { assert(C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&& "SrcTy must be larger than DestTy for Trunc!"); - return getFoldedCast(Instruction::Trunc, C, Ty); + return getFoldedCast(Instruction::Trunc, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) { +Constant *ConstantExpr::getSExt(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1609,10 +1681,10 @@ Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) { assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "SrcTy must be smaller than DestTy for SExt!"); - return getFoldedCast(Instruction::SExt, C, Ty); + return getFoldedCast(Instruction::SExt, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) { +Constant *ConstantExpr::getZExt(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1623,10 +1695,10 @@ Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) { assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "SrcTy must be smaller than DestTy for ZExt!"); - return getFoldedCast(Instruction::ZExt, C, Ty); + return getFoldedCast(Instruction::ZExt, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1635,10 +1707,10 @@ Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) { assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&& "This is an illegal floating point truncation!"); - return getFoldedCast(Instruction::FPTrunc, C, Ty); + return getFoldedCast(Instruction::FPTrunc, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1647,10 +1719,10 @@ Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) { assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "This is an illegal floating point extension!"); - return getFoldedCast(Instruction::FPExt, C, Ty); + return getFoldedCast(Instruction::FPExt, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) { +Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1658,10 +1730,10 @@ Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() && "This is an illegal uint to floating point cast!"); - return getFoldedCast(Instruction::UIToFP, C, Ty); + return getFoldedCast(Instruction::UIToFP, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) { +Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1669,10 +1741,10 @@ Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() && "This is an illegal sint to floating point cast!"); - return getFoldedCast(Instruction::SIToFP, C, Ty); + return getFoldedCast(Instruction::SIToFP, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1680,10 +1752,10 @@ Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() && "This is an illegal floating point to uint cast!"); - return getFoldedCast(Instruction::FPToUI, C, Ty); + return getFoldedCast(Instruction::FPToUI, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1691,10 +1763,11 @@ Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() && "This is an illegal floating point to sint cast!"); - return getFoldedCast(Instruction::FPToSI, C, Ty); + return getFoldedCast(Instruction::FPToSI, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(C->getType()->getScalarType()->isPointerTy() && "PtrToInt source must be pointer or pointer vector"); assert(DstTy->getScalarType()->isIntegerTy() && @@ -1703,10 +1776,11 @@ Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) { if (isa<VectorType>(C->getType())) assert(C->getType()->getVectorNumElements()==DstTy->getVectorNumElements()&& "Invalid cast between a different number of vector elements"); - return getFoldedCast(Instruction::PtrToInt, C, DstTy); + return getFoldedCast(Instruction::PtrToInt, C, DstTy, OnlyIfReduced); } -Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(C->getType()->getScalarType()->isIntegerTy() && "IntToPtr source must be integer or integer vector"); assert(DstTy->getScalarType()->isPointerTy() && @@ -1715,10 +1789,11 @@ Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) { if (isa<VectorType>(C->getType())) assert(C->getType()->getVectorNumElements()==DstTy->getVectorNumElements()&& "Invalid cast between a different number of vector elements"); - return getFoldedCast(Instruction::IntToPtr, C, DstTy); + return getFoldedCast(Instruction::IntToPtr, C, DstTy, OnlyIfReduced); } -Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(CastInst::castIsValid(Instruction::BitCast, C, DstTy) && "Invalid constantexpr bitcast!"); @@ -1726,10 +1801,11 @@ Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) { // speedily. if (C->getType() == DstTy) return C; - return getFoldedCast(Instruction::BitCast, C, DstTy); + return getFoldedCast(Instruction::BitCast, C, DstTy, OnlyIfReduced); } -Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) && "Invalid constantexpr addrspacecast!"); @@ -1746,11 +1822,11 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) { } C = getBitCast(C, MidTy); } - return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy); + return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy, OnlyIfReduced); } Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags) { + unsigned Flags, Type *OnlyIfReducedTy) { // Check the operands for consistency first. assert(Opcode >= Instruction::BinaryOpsBegin && Opcode < Instruction::BinaryOpsEnd && @@ -1819,8 +1895,11 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2)) return FC; // Fold a few common cases. + if (OnlyIfReducedTy == C1->getType()) + return nullptr; + Constant *ArgVec[] = { C1, C2 }; - ExprMapKeyType Key(Opcode, ArgVec, 0, Flags); + ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags); LLVMContextImpl *pImpl = C1->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(C1->getType(), Key); @@ -1840,7 +1919,7 @@ Constant *ConstantExpr::getAlignOf(Type* Ty) { // alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1 // Note that a non-inbounds gep is used, as null isn't within any object. Type *AligningTy = - StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, NULL); + StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, nullptr); Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo(0)); Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0); Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1); @@ -1868,8 +1947,8 @@ Constant *ConstantExpr::getOffsetOf(Type* Ty, Constant *FieldNo) { Type::getInt64Ty(Ty->getContext())); } -Constant *ConstantExpr::getCompare(unsigned short Predicate, - Constant *C1, Constant *C2) { +Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1, + Constant *C2, bool OnlyIfReduced) { assert(C1->getType() == C2->getType() && "Op types should be identical!"); switch (Predicate) { @@ -1880,31 +1959,35 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate, case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULE: case CmpInst::FCMP_UNE: case CmpInst::FCMP_TRUE: - return getFCmp(Predicate, C1, C2); + return getFCmp(Predicate, C1, C2, OnlyIfReduced); case CmpInst::ICMP_EQ: case CmpInst::ICMP_NE: case CmpInst::ICMP_UGT: case CmpInst::ICMP_UGE: case CmpInst::ICMP_ULT: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: case CmpInst::ICMP_SLT: case CmpInst::ICMP_SLE: - return getICmp(Predicate, C1, C2); + return getICmp(Predicate, C1, C2, OnlyIfReduced); } } -Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) { +Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2, + Type *OnlyIfReducedTy) { assert(!SelectInst::areInvalidOperands(C, V1, V2)&&"Invalid select operands"); if (Constant *SC = ConstantFoldSelectInstruction(C, V1, V2)) return SC; // Fold common cases + if (OnlyIfReducedTy == V1->getType()) + return nullptr; + Constant *ArgVec[] = { C, V1, V2 }; - ExprMapKeyType Key(Instruction::Select, ArgVec); + ConstantExprKeyType Key(Instruction::Select, ArgVec); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(V1->getType(), Key); } Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, - bool InBounds) { + bool InBounds, Type *OnlyIfReducedTy) { assert(C->getType()->isPtrOrPtrVectorTy() && "Non-pointer type for constant GetElementPtr expression"); @@ -1919,6 +2002,9 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, if (VectorType *VecTy = dyn_cast<VectorType>(C->getType())) ReqTy = VectorType::get(ReqTy, VecTy->getNumElements()); + if (OnlyIfReducedTy == ReqTy) + return nullptr; + // Look up the constant in the table first to ensure uniqueness std::vector<Constant*> ArgVec; ArgVec.reserve(1 + Idxs.size()); @@ -1932,15 +2018,15 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, "getelementptr index type missmatch"); ArgVec.push_back(cast<Constant>(Idxs[i])); } - const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0, - InBounds ? GEPOperator::IsInBounds : 0); + const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0, + InBounds ? GEPOperator::IsInBounds : 0); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant * -ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { +Constant *ConstantExpr::getICmp(unsigned short pred, Constant *LHS, + Constant *RHS, bool OnlyIfReduced) { assert(LHS->getType() == RHS->getType()); assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE && pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate"); @@ -1948,10 +2034,13 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS)) return FC; // Fold a few common cases... + if (OnlyIfReduced) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { LHS, RHS }; // Get the key type with both the opcode and predicate - const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred); + const ConstantExprKeyType Key(Instruction::ICmp, ArgVec, pred); Type *ResultTy = Type::getInt1Ty(LHS->getContext()); if (VectorType *VT = dyn_cast<VectorType>(LHS->getType())) @@ -1961,18 +2050,21 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { return pImpl->ExprConstants.getOrCreate(ResultTy, Key); } -Constant * -ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) { +Constant *ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, + Constant *RHS, bool OnlyIfReduced) { assert(LHS->getType() == RHS->getType()); assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate"); if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS)) return FC; // Fold a few common cases... + if (OnlyIfReduced) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { LHS, RHS }; // Get the key type with both the opcode and predicate - const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred); + const ConstantExprKeyType Key(Instruction::FCmp, ArgVec, pred); Type *ResultTy = Type::getInt1Ty(LHS->getContext()); if (VectorType *VT = dyn_cast<VectorType>(LHS->getType())) @@ -1982,7 +2074,8 @@ ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) { return pImpl->ExprConstants.getOrCreate(ResultTy, Key); } -Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { +Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx, + Type *OnlyIfReducedTy) { assert(Val->getType()->isVectorTy() && "Tried to create extractelement operation on non-vector type!"); assert(Idx->getType()->isIntegerTy() && @@ -1991,17 +2084,20 @@ Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx)) return FC; // Fold a few common cases. + Type *ReqTy = Val->getType()->getVectorElementType(); + if (OnlyIfReducedTy == ReqTy) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { Val, Idx }; - const ExprMapKeyType Key(Instruction::ExtractElement, ArgVec); + const ConstantExprKeyType Key(Instruction::ExtractElement, ArgVec); LLVMContextImpl *pImpl = Val->getContext().pImpl; - Type *ReqTy = Val->getType()->getVectorElementType(); return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, - Constant *Idx) { +Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, + Constant *Idx, Type *OnlyIfReducedTy) { assert(Val->getType()->isVectorTy() && "Tried to create insertelement operation on non-vector type!"); assert(Elt->getType() == Val->getType()->getVectorElementType() && @@ -2011,16 +2107,20 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, Idx)) return FC; // Fold a few common cases. + + if (OnlyIfReducedTy == Val->getType()) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { Val, Elt, Idx }; - const ExprMapKeyType Key(Instruction::InsertElement, ArgVec); + const ConstantExprKeyType Key(Instruction::InsertElement, ArgVec); LLVMContextImpl *pImpl = Val->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(Val->getType(), Key); } -Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, - Constant *Mask) { +Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, + Constant *Mask, Type *OnlyIfReducedTy) { assert(ShuffleVectorInst::isValidOperands(V1, V2, Mask) && "Invalid shuffle vector constant expr operands!"); @@ -2031,16 +2131,20 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, Type *EltTy = V1->getType()->getVectorElementType(); Type *ShufTy = VectorType::get(EltTy, NElts); + if (OnlyIfReducedTy == ShufTy) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { V1, V2, Mask }; - const ExprMapKeyType Key(Instruction::ShuffleVector, ArgVec); + const ConstantExprKeyType Key(Instruction::ShuffleVector, ArgVec); LLVMContextImpl *pImpl = ShufTy->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ShufTy, Key); } Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, - ArrayRef<unsigned> Idxs) { + ArrayRef<unsigned> Idxs, + Type *OnlyIfReducedTy) { assert(Agg->getType()->isFirstClassType() && "Non-first-class type for constant insertvalue expression"); @@ -2052,15 +2156,18 @@ Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, if (Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs)) return FC; + if (OnlyIfReducedTy == ReqTy) + return nullptr; + Constant *ArgVec[] = { Agg, Val }; - const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); + const ConstantExprKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); LLVMContextImpl *pImpl = Agg->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant *ConstantExpr::getExtractValue(Constant *Agg, - ArrayRef<unsigned> Idxs) { +Constant *ConstantExpr::getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs, + Type *OnlyIfReducedTy) { assert(Agg->getType()->isFirstClassType() && "Tried to create extractelement operation on non-first-class type!"); @@ -2073,8 +2180,11 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, if (Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs)) return FC; + if (OnlyIfReducedTy == ReqTy) + return nullptr; + Constant *ArgVec[] = { Agg }; - const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); + const ConstantExprKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); LLVMContextImpl *pImpl = Agg->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -2326,14 +2436,16 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { return ConstantAggregateZero::get(Ty); // Do a lookup to see if we have already formed one of these. - StringMap<ConstantDataSequential*>::MapEntryTy &Slot = - Ty->getContext().pImpl->CDSConstants.GetOrCreateValue(Elements); + auto &Slot = + *Ty->getContext() + .pImpl->CDSConstants.insert(std::make_pair(Elements, nullptr)) + .first; // The bucket can point to a linked list of different CDS's that have the same // body but different types. For example, 0,0,0,1 could be a 4 element array // of i8, or a 1-element array of i32. They'll both end up in the same /// StringMap bucket, linked up by their Next pointers. Walk the list. - ConstantDataSequential **Entry = &Slot.getValue(); + ConstantDataSequential **Entry = &Slot.second; for (ConstantDataSequential *Node = *Entry; Node; Entry = &Node->Next, Node = *Entry) if (Node->getType() == Ty) @@ -2342,10 +2454,10 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { // Okay, we didn't get a hit. Create a node of the right class, link it in, // and return it. if (isa<ArrayType>(Ty)) - return *Entry = new ConstantDataArray(Ty, Slot.getKeyData()); + return *Entry = new ConstantDataArray(Ty, Slot.first().data()); assert(isa<VectorType>(Ty)); - return *Entry = new ConstantDataVector(Ty, Slot.getKeyData()); + return *Entry = new ConstantDataVector(Ty, Slot.first().data()); } void ConstantDataSequential::destroyConstant() { @@ -2431,7 +2543,7 @@ Constant *ConstantDataArray::getString(LLVMContext &Context, StringRef Str, bool AddNull) { if (!AddNull) { const uint8_t *Data = reinterpret_cast<const uint8_t *>(Str.data()); - return get(Context, ArrayRef<uint8_t>(const_cast<uint8_t *>(Data), + return get(Context, makeArrayRef(const_cast<uint8_t *>(Data), Str.size())); } @@ -2602,7 +2714,7 @@ bool ConstantDataSequential::isCString() const { } /// getSplatValue - If this is a splat constant, meaning that all of the -/// elements have the same value, return that value. Otherwise return NULL. +/// elements have the same value, return that value. Otherwise return nullptr. Constant *ConstantDataVector::getSplatValue() const { const char *Base = getRawDataValues().data(); @@ -2630,16 +2742,23 @@ Constant *ConstantDataVector::getSplatValue() const { /// work, but would be really slow because it would have to unique each updated /// array instance. /// +void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) { + // I do need to replace this with an existing value. + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement. + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast<Constant>(To); - LLVMContextImpl *pImpl = getType()->getContext().pImpl; - SmallVector<Constant*, 8> Values; - LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup; - Lookup.first = cast<ArrayType>(getType()); Values.reserve(getNumOperands()); // Build replacement array. // Fill values with the modified operands of the constant array. Also, @@ -2658,51 +2777,25 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, AllSame &= Val == ToC; } - Constant *Replacement = nullptr; if (AllSame && ToC->isNullValue()) { - Replacement = ConstantAggregateZero::get(getType()); - } else if (AllSame && isa<UndefValue>(ToC)) { - Replacement = UndefValue::get(getType()); - } else { - // Check to see if we have this array type already. - Lookup.second = makeArrayRef(Values); - LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I = - pImpl->ArrayConstants.find(Lookup); - - if (I != pImpl->ArrayConstants.map_end()) { - Replacement = I->first; - } else { - // Okay, the new shape doesn't exist in the system yet. Instead of - // creating a new constant array, inserting it, replaceallusesof'ing the - // old with the new, then deleting the old... just update the current one - // in place! - pImpl->ArrayConstants.remove(this); - - // Update to the new value. Optimize for the case when we have a single - // operand that we're changing, but handle bulk updates efficiently. - if (NumUpdated == 1) { - unsigned OperandToUpdate = U - OperandList; - assert(getOperand(OperandToUpdate) == From && - "ReplaceAllUsesWith broken!"); - setOperand(OperandToUpdate, ToC); - } else { - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (getOperand(i) == From) - setOperand(i, ToC); - } - pImpl->ArrayConstants.insert(this); - return; - } + replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType())); + return; + } + if (AllSame && isa<UndefValue>(ToC)) { + replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); + return; } - // Otherwise, I do need to replace this with an existing value. - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); + // Check for any other type of constant-folding. + if (Constant *C = getImpl(getType(), Values)) { + replaceUsesOfWithOnConstantImpl(C); + return; + } - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->ArrayConstants.replaceOperandsInPlace( + Values, this, From, ToC, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, @@ -2714,8 +2807,6 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); SmallVector<Constant*, 8> Values; - LLVMContextImpl::StructConstantsTy::LookupKey Lookup; - Lookup.first = cast<StructType>(getType()); Values.reserve(getNumOperands()); // Build replacement struct. // Fill values with the modified operands of the constant struct. Also, @@ -2742,64 +2833,47 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, } Values[OperandToUpdate] = ToC; - LLVMContextImpl *pImpl = getContext().pImpl; - - Constant *Replacement = nullptr; if (isAllZeros) { - Replacement = ConstantAggregateZero::get(getType()); - } else if (isAllUndef) { - Replacement = UndefValue::get(getType()); - } else { - // Check to see if we have this struct type already. - Lookup.second = makeArrayRef(Values); - LLVMContextImpl::StructConstantsTy::MapTy::iterator I = - pImpl->StructConstants.find(Lookup); - - if (I != pImpl->StructConstants.map_end()) { - Replacement = I->first; - } else { - // Okay, the new shape doesn't exist in the system yet. Instead of - // creating a new constant struct, inserting it, replaceallusesof'ing the - // old with the new, then deleting the old... just update the current one - // in place! - pImpl->StructConstants.remove(this); - - // Update to the new value. - setOperand(OperandToUpdate, ToC); - pImpl->StructConstants.insert(this); - return; - } + replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType())); + return; + } + if (isAllUndef) { + replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); + return; } - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->StructConstants.replaceOperandsInPlace( + Values, this, From, ToC)) + replaceUsesOfWithOnConstantImpl(C); } void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast<Constant>(To); SmallVector<Constant*, 8> Values; Values.reserve(getNumOperands()); // Build replacement array... + unsigned NumUpdated = 0; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Val = getOperand(i); - if (Val == From) Val = cast<Constant>(To); + if (Val == From) { + ++NumUpdated; + Val = ToC; + } Values.push_back(Val); } - Constant *Replacement = get(Values); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); + if (Constant *C = getImpl(Values)) { + replaceUsesOfWithOnConstantImpl(C); + return; + } - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace( + Values, this, From, ToC, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, @@ -2808,19 +2882,26 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Constant *To = cast<Constant>(ToV); SmallVector<Constant*, 8> NewOps; + unsigned NumUpdated = 0; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Op = getOperand(i); - NewOps.push_back(Op == From ? To : Op); + if (Op == From) { + ++NumUpdated; + Op = To; + } + NewOps.push_back(Op); } + assert(NumUpdated && "I didn't contain From!"); - Constant *Replacement = getWithOperands(NewOps); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); + if (Constant *C = getWithOperands(NewOps, getType(), true)) { + replaceUsesOfWithOnConstantImpl(C); + return; + } - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace( + NewOps, this, From, To, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } Instruction *ConstantExpr::getAsInstruction() { diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h index f06509fb73..571dec2e0f 100644 --- a/lib/IR/ConstantsContext.h +++ b/lib/IR/ConstantsContext.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CONSTANTSCONTEXT_H -#define LLVM_CONSTANTSCONTEXT_H +#ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H +#define LLVM_LIB_IR_CONSTANTSCONTEXT_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" @@ -29,8 +29,6 @@ #define DEBUG_TYPE "ir" namespace llvm { -template<class ValType> -struct ConstantTraits; /// UnaryConstantExpr - This class is private to Constants.cpp, and is used /// behind the scenes to implement unary constant exprs. @@ -169,11 +167,10 @@ public: void *operator new(size_t s) { return User::operator new(s, 1); } - ExtractValueConstantExpr(Constant *Agg, - const SmallVector<unsigned, 4> &IdxList, + ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList, Type *DestTy) - : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1), - Indices(IdxList) { + : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1), + Indices(IdxList.begin(), IdxList.end()) { Op<0>() = Agg; } @@ -196,10 +193,9 @@ public: return User::operator new(s, 2); } InsertValueConstantExpr(Constant *Agg, Constant *Val, - const SmallVector<unsigned, 4> &IdxList, - Type *DestTy) - : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2), - Indices(IdxList) { + ArrayRef<unsigned> IdxList, Type *DestTy) + : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2), + Indices(IdxList.begin(), IdxList.end()) { Op<0>() = Agg; Op<1>() = Val; } @@ -316,379 +312,241 @@ struct OperandTraits<CompareConstantExpr> : }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) -struct ExprMapKeyType { - ExprMapKeyType(unsigned opc, - ArrayRef<Constant*> ops, - unsigned short flags = 0, - unsigned short optionalflags = 0, - ArrayRef<unsigned> inds = None) - : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), - operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {} - uint8_t opcode; - uint8_t subclassoptionaldata; - uint16_t subclassdata; - std::vector<Constant*> operands; - SmallVector<unsigned, 4> indices; - bool operator==(const ExprMapKeyType& that) const { - return this->opcode == that.opcode && - this->subclassdata == that.subclassdata && - this->subclassoptionaldata == that.subclassoptionaldata && - this->operands == that.operands && - this->indices == that.indices; - } - bool operator<(const ExprMapKeyType & that) const { - return std::tie(opcode, operands, subclassdata, subclassoptionaldata, - indices) < - std::tie(that.opcode, that.operands, that.subclassdata, - that.subclassoptionaldata, that.indices); - } - - bool operator!=(const ExprMapKeyType& that) const { - return !(*this == that); - } -}; - -struct InlineAsmKeyType { - InlineAsmKeyType(StringRef AsmString, - StringRef Constraints, bool hasSideEffects, - bool isAlignStack, InlineAsm::AsmDialect asmDialect) - : asm_string(AsmString), constraints(Constraints), - has_side_effects(hasSideEffects), is_align_stack(isAlignStack), - asm_dialect(asmDialect) {} - std::string asm_string; - std::string constraints; - bool has_side_effects; - bool is_align_stack; - InlineAsm::AsmDialect asm_dialect; - bool operator==(const InlineAsmKeyType& that) const { - return this->asm_string == that.asm_string && - this->constraints == that.constraints && - this->has_side_effects == that.has_side_effects && - this->is_align_stack == that.is_align_stack && - this->asm_dialect == that.asm_dialect; - } - bool operator<(const InlineAsmKeyType& that) const { - return std::tie(asm_string, constraints, has_side_effects, is_align_stack, - asm_dialect) < - std::tie(that.asm_string, that.constraints, that.has_side_effects, - that.is_align_stack, that.asm_dialect); - } - - bool operator!=(const InlineAsmKeyType& that) const { - return !(*this == that); - } -}; +template <class ConstantClass> struct ConstantAggrKeyType; +struct InlineAsmKeyType; +struct ConstantExprKeyType; -// The number of operands for each ConstantCreator::create method is -// determined by the ConstantTraits template. -// ConstantCreator - A class that is used to create constants by -// ConstantUniqueMap*. This class should be partially specialized if there is -// something strange that needs to be done to interface to the ctor for the -// constant. -// -template<typename T, typename Alloc> -struct ConstantTraits< std::vector<T, Alloc> > { - static unsigned uses(const std::vector<T, Alloc>& v) { - return v.size(); - } -}; - -template<> -struct ConstantTraits<Constant *> { - static unsigned uses(Constant * const & v) { - return 1; - } +template <class ConstantClass> struct ConstantInfo; +template <> struct ConstantInfo<ConstantExpr> { + typedef ConstantExprKeyType ValType; + typedef Type TypeClass; }; - -template<class ConstantClass, class TypeClass, class ValType> -struct ConstantCreator { - static ConstantClass *create(TypeClass *Ty, const ValType &V) { - return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V); +template <> struct ConstantInfo<InlineAsm> { + typedef InlineAsmKeyType ValType; + typedef PointerType TypeClass; +}; +template <> struct ConstantInfo<ConstantArray> { + typedef ConstantAggrKeyType<ConstantArray> ValType; + typedef ArrayType TypeClass; +}; +template <> struct ConstantInfo<ConstantStruct> { + typedef ConstantAggrKeyType<ConstantStruct> ValType; + typedef StructType TypeClass; +}; +template <> struct ConstantInfo<ConstantVector> { + typedef ConstantAggrKeyType<ConstantVector> ValType; + typedef VectorType TypeClass; +}; + +template <class ConstantClass> struct ConstantAggrKeyType { + ArrayRef<Constant *> Operands; + ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {} + ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *) + : Operands(Operands) {} + ConstantAggrKeyType(const ConstantClass *C, + SmallVectorImpl<Constant *> &Storage) { + assert(Storage.empty() && "Expected empty storage"); + for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) + Storage.push_back(C->getOperand(I)); + Operands = Storage; + } + + bool operator==(const ConstantAggrKeyType &X) const { + return Operands == X.Operands; + } + bool operator==(const ConstantClass *C) const { + if (Operands.size() != C->getNumOperands()) + return false; + for (unsigned I = 0, E = Operands.size(); I != E; ++I) + if (Operands[I] != C->getOperand(I)) + return false; + return true; } -}; - -template<class ConstantClass, class TypeClass> -struct ConstantArrayCreator { - static ConstantClass *create(TypeClass *Ty, ArrayRef<Constant*> V) { - return new(V.size()) ConstantClass(Ty, V); + unsigned getHash() const { + return hash_combine_range(Operands.begin(), Operands.end()); } -}; -template<class ConstantClass> -struct ConstantKeyData { - typedef void ValType; - static ValType getValType(ConstantClass *C) { - llvm_unreachable("Unknown Constant type!"); + typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass; + ConstantClass *create(TypeClass *Ty) const { + return new (Operands.size()) ConstantClass(Ty, Operands); } }; -template<> -struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> { - static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V, - unsigned short pred = 0) { - if (Instruction::isCast(V.opcode)) - return new UnaryConstantExpr(V.opcode, V.operands[0], Ty); - if ((V.opcode >= Instruction::BinaryOpsBegin && - V.opcode < Instruction::BinaryOpsEnd)) - return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1], - V.subclassoptionaldata); - if (V.opcode == Instruction::Select) - return new SelectConstantExpr(V.operands[0], V.operands[1], - V.operands[2]); - if (V.opcode == Instruction::ExtractElement) - return new ExtractElementConstantExpr(V.operands[0], V.operands[1]); - if (V.opcode == Instruction::InsertElement) - return new InsertElementConstantExpr(V.operands[0], V.operands[1], - V.operands[2]); - if (V.opcode == Instruction::ShuffleVector) - return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1], - V.operands[2]); - if (V.opcode == Instruction::InsertValue) - return new InsertValueConstantExpr(V.operands[0], V.operands[1], - V.indices, Ty); - if (V.opcode == Instruction::ExtractValue) - return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty); - if (V.opcode == Instruction::GetElementPtr) { - std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end()); - return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty, - V.subclassoptionaldata); +struct InlineAsmKeyType { + StringRef AsmString; + StringRef Constraints; + bool HasSideEffects; + bool IsAlignStack; + InlineAsm::AsmDialect AsmDialect; + + InlineAsmKeyType(StringRef AsmString, StringRef Constraints, + bool HasSideEffects, bool IsAlignStack, + InlineAsm::AsmDialect AsmDialect) + : AsmString(AsmString), Constraints(Constraints), + HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack), + AsmDialect(AsmDialect) {} + InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &) + : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()), + HasSideEffects(Asm->hasSideEffects()), + IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {} + + bool operator==(const InlineAsmKeyType &X) const { + return HasSideEffects == X.HasSideEffects && + IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect && + AsmString == X.AsmString && Constraints == X.Constraints; + } + bool operator==(const InlineAsm *Asm) const { + return HasSideEffects == Asm->hasSideEffects() && + IsAlignStack == Asm->isAlignStack() && + AsmDialect == Asm->getDialect() && + AsmString == Asm->getAsmString() && + Constraints == Asm->getConstraintString(); + } + unsigned getHash() const { + return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack, + AsmDialect); + } + + typedef ConstantInfo<InlineAsm>::TypeClass TypeClass; + InlineAsm *create(TypeClass *Ty) const { + return new InlineAsm(Ty, AsmString, Constraints, HasSideEffects, + IsAlignStack, AsmDialect); + } +}; + +struct ConstantExprKeyType { + uint8_t Opcode; + uint8_t SubclassOptionalData; + uint16_t SubclassData; + ArrayRef<Constant *> Ops; + ArrayRef<unsigned> Indexes; + + ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops, + unsigned short SubclassData = 0, + unsigned short SubclassOptionalData = 0, + ArrayRef<unsigned> Indexes = None) + : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), + SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {} + ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE) + : Opcode(CE->getOpcode()), + SubclassOptionalData(CE->getRawSubclassOptionalData()), + SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands), + Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) {} + ConstantExprKeyType(const ConstantExpr *CE, + SmallVectorImpl<Constant *> &Storage) + : Opcode(CE->getOpcode()), + SubclassOptionalData(CE->getRawSubclassOptionalData()), + SubclassData(CE->isCompare() ? CE->getPredicate() : 0), + Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) { + assert(Storage.empty() && "Expected empty storage"); + for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I) + Storage.push_back(CE->getOperand(I)); + Ops = Storage; + } + + bool operator==(const ConstantExprKeyType &X) const { + return Opcode == X.Opcode && SubclassData == X.SubclassData && + SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops && + Indexes == X.Indexes; + } + + bool operator==(const ConstantExpr *CE) const { + if (Opcode != CE->getOpcode()) + return false; + if (SubclassOptionalData != CE->getRawSubclassOptionalData()) + return false; + if (Ops.size() != CE->getNumOperands()) + return false; + if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0)) + return false; + for (unsigned I = 0, E = Ops.size(); I != E; ++I) + if (Ops[I] != CE->getOperand(I)) + return false; + if (Indexes != (CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>())) + return false; + return true; + } + + unsigned getHash() const { + return hash_combine(Opcode, SubclassOptionalData, SubclassData, + hash_combine_range(Ops.begin(), Ops.end()), + hash_combine_range(Indexes.begin(), Indexes.end())); + } + + typedef ConstantInfo<ConstantExpr>::TypeClass TypeClass; + ConstantExpr *create(TypeClass *Ty) const { + switch (Opcode) { + default: + if (Instruction::isCast(Opcode)) + return new UnaryConstantExpr(Opcode, Ops[0], Ty); + if ((Opcode >= Instruction::BinaryOpsBegin && + Opcode < Instruction::BinaryOpsEnd)) + return new BinaryConstantExpr(Opcode, Ops[0], Ops[1], + SubclassOptionalData); + llvm_unreachable("Invalid ConstantExpr!"); + case Instruction::Select: + return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]); + case Instruction::ExtractElement: + return new ExtractElementConstantExpr(Ops[0], Ops[1]); + case Instruction::InsertElement: + return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]); + case Instruction::ShuffleVector: + return new ShuffleVectorConstantExpr(Ops[0], Ops[1], Ops[2]); + case Instruction::InsertValue: + return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty); + case Instruction::ExtractValue: + return new ExtractValueConstantExpr(Ops[0], Indexes, Ty); + case Instruction::GetElementPtr: + return GetElementPtrConstantExpr::Create(Ops[0], Ops.slice(1), Ty, + SubclassOptionalData); + case Instruction::ICmp: + return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData, + Ops[0], Ops[1]); + case Instruction::FCmp: + return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData, + Ops[0], Ops[1]); } - - // The compare instructions are weird. We have to encode the predicate - // value and it is combined with the instruction opcode by multiplying - // the opcode by one hundred. We must decode this to get the predicate. - if (V.opcode == Instruction::ICmp) - return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata, - V.operands[0], V.operands[1]); - if (V.opcode == Instruction::FCmp) - return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata, - V.operands[0], V.operands[1]); - llvm_unreachable("Invalid ConstantExpr!"); - } -}; - -template<> -struct ConstantKeyData<ConstantExpr> { - typedef ExprMapKeyType ValType; - static ValType getValType(ConstantExpr *CE) { - std::vector<Constant*> Operands; - Operands.reserve(CE->getNumOperands()); - for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) - Operands.push_back(cast<Constant>(CE->getOperand(i))); - return ExprMapKeyType(CE->getOpcode(), Operands, - CE->isCompare() ? CE->getPredicate() : 0, - CE->getRawSubclassOptionalData(), - CE->hasIndices() ? - CE->getIndices() : ArrayRef<unsigned>()); - } -}; - -template<> -struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> { - static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) { - return new InlineAsm(Ty, Key.asm_string, Key.constraints, - Key.has_side_effects, Key.is_align_stack, - Key.asm_dialect); } }; -template<> -struct ConstantKeyData<InlineAsm> { - typedef InlineAsmKeyType ValType; - static ValType getValType(InlineAsm *Asm) { - return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(), - Asm->hasSideEffects(), Asm->isAlignStack(), - Asm->getDialect()); - } -}; - -template<class ValType, class ValRefType, class TypeClass, class ConstantClass, - bool HasLargeKey = false /*true for arrays and structs*/ > -class ConstantUniqueMap { -public: - typedef std::pair<TypeClass*, ValType> MapKey; - typedef std::map<MapKey, ConstantClass *> MapTy; - typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy; -private: - /// Map - This is the main map from the element descriptor to the Constants. - /// This is the primary way we avoid creating two of the same shape - /// constant. - MapTy Map; - - /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping - /// from the constants to their element in Map. This is important for - /// removal of constants from the array, which would otherwise have to scan - /// through the map with very large keys. - InverseMapTy InverseMap; - -public: - typename MapTy::iterator map_begin() { return Map.begin(); } - typename MapTy::iterator map_end() { return Map.end(); } - - void freeConstants() { - for (typename MapTy::iterator I=Map.begin(), E=Map.end(); - I != E; ++I) { - // Asserts that use_empty(). - delete I->second; - } - } - - /// InsertOrGetItem - Return an iterator for the specified element. - /// If the element exists in the map, the returned iterator points to the - /// entry and Exists=true. If not, the iterator points to the newly - /// inserted entry and returns Exists=false. Newly inserted entries have - /// I->second == 0, and should be filled in. - typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, ConstantClass *> - &InsertVal, - bool &Exists) { - std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal); - Exists = !IP.second; - return IP.first; - } - -private: - typename MapTy::iterator FindExistingElement(ConstantClass *CP) { - if (HasLargeKey) { - typename InverseMapTy::iterator IMI = InverseMap.find(CP); - assert(IMI != InverseMap.end() && IMI->second != Map.end() && - IMI->second->second == CP && - "InverseMap corrupt!"); - return IMI->second; - } - - typename MapTy::iterator I = - Map.find(MapKey(static_cast<TypeClass*>(CP->getType()), - ConstantKeyData<ConstantClass>::getValType(CP))); - if (I == Map.end() || I->second != CP) { - // FIXME: This should not use a linear scan. If this gets to be a - // performance problem, someone should look at this. - for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) - /* empty */; - } - return I; - } - - ConstantClass *Create(TypeClass *Ty, ValRefType V, - typename MapTy::iterator I) { - ConstantClass* Result = - ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V); - - assert(Result->getType() == Ty && "Type specified is not correct!"); - I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.insert(std::make_pair(Result, I)); - - return Result; - } +template <class ConstantClass> class ConstantUniqueMap { public: - - /// getOrCreate - Return the specified constant from the map, creating it if - /// necessary. - ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) { - MapKey Lookup(Ty, V); - ConstantClass* Result = nullptr; - - typename MapTy::iterator I = Map.find(Lookup); - // Is it in the map? - if (I != Map.end()) - Result = I->second; - - if (!Result) { - // If no preexisting value, create one now... - Result = Create(Ty, V, I); - } - - return Result; - } - - void remove(ConstantClass *CP) { - typename MapTy::iterator I = FindExistingElement(CP); - assert(I != Map.end() && "Constant not found in constant table!"); - assert(I->second == CP && "Didn't find correct element?"); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.erase(CP); - - Map.erase(I); - } - - /// MoveConstantToNewSlot - If we are about to change C to be the element - /// specified by I, update our internal data structures to reflect this - /// fact. - void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) { - // First, remove the old location of the specified constant in the map. - typename MapTy::iterator OldI = FindExistingElement(C); - assert(OldI != Map.end() && "Constant not found in constant table!"); - assert(OldI->second == C && "Didn't find correct element?"); - - // Remove the old entry from the map. - Map.erase(OldI); - - // Update the inverse map so that we know that this constant is now - // located at descriptor I. - if (HasLargeKey) { - assert(I->second == C && "Bad inversemap entry!"); - InverseMap[C] = I; - } - } + typedef typename ConstantInfo<ConstantClass>::ValType ValType; + typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass; + typedef std::pair<TypeClass *, ValType> LookupKey; - void dump() const { - DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); - } -}; - -// Unique map for aggregate constants -template<class TypeClass, class ConstantClass> -class ConstantAggrUniqueMap { -public: - typedef ArrayRef<Constant*> Operands; - typedef std::pair<TypeClass*, Operands> LookupKey; private: struct MapInfo { - typedef DenseMapInfo<ConstantClass*> ConstantClassInfo; - typedef DenseMapInfo<Constant*> ConstantInfo; - typedef DenseMapInfo<TypeClass*> TypeClassInfo; - static inline ConstantClass* getEmptyKey() { + typedef DenseMapInfo<ConstantClass *> ConstantClassInfo; + static inline ConstantClass *getEmptyKey() { return ConstantClassInfo::getEmptyKey(); } - static inline ConstantClass* getTombstoneKey() { + static inline ConstantClass *getTombstoneKey() { return ConstantClassInfo::getTombstoneKey(); } static unsigned getHashValue(const ConstantClass *CP) { - SmallVector<Constant*, 8> CPOperands; - CPOperands.reserve(CP->getNumOperands()); - for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I) - CPOperands.push_back(CP->getOperand(I)); - return getHashValue(LookupKey(CP->getType(), CPOperands)); + SmallVector<Constant *, 8> Storage; + return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage))); } static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) { return LHS == RHS; } static unsigned getHashValue(const LookupKey &Val) { - return hash_combine(Val.first, hash_combine_range(Val.second.begin(), - Val.second.end())); + return hash_combine(Val.first, Val.second.getHash()); } static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) { if (RHS == getEmptyKey() || RHS == getTombstoneKey()) return false; - if (LHS.first != RHS->getType() - || LHS.second.size() != RHS->getNumOperands()) + if (LHS.first != RHS->getType()) return false; - for (unsigned I = 0, E = RHS->getNumOperands(); I < E; ++I) { - if (LHS.second[I] != RHS->getOperand(I)) - return false; - } - return true; + return LHS.second == RHS; } }; + public: typedef DenseMap<ConstantClass *, char, MapInfo> MapTy; private: - /// Map - This is the main map from the element descriptor to the Constants. - /// This is the primary way we avoid creating two of the same shape - /// constant. MapTy Map; public: @@ -696,44 +554,33 @@ public: typename MapTy::iterator map_end() { return Map.end(); } void freeConstants() { - for (typename MapTy::iterator I=Map.begin(), E=Map.end(); - I != E; ++I) { + for (auto &I : Map) // Asserts that use_empty(). - delete I->first; - } + delete I.first; } private: - typename MapTy::iterator findExistingElement(ConstantClass *CP) { - return Map.find(CP); - } - - ConstantClass *Create(TypeClass *Ty, Operands V, typename MapTy::iterator I) { - ConstantClass* Result = - ConstantArrayCreator<ConstantClass,TypeClass>::create(Ty, V); + ConstantClass *create(TypeClass *Ty, ValType V) { + ConstantClass *Result = V.create(Ty); assert(Result->getType() == Ty && "Type specified is not correct!"); - Map[Result] = '\0'; + insert(Result); return Result; } -public: - /// getOrCreate - Return the specified constant from the map, creating it if - /// necessary. - ConstantClass *getOrCreate(TypeClass *Ty, Operands V) { +public: + /// Return the specified constant from the map, creating it if necessary. + ConstantClass *getOrCreate(TypeClass *Ty, ValType V) { LookupKey Lookup(Ty, V); - ConstantClass* Result = nullptr; + ConstantClass *Result = nullptr; - typename MapTy::iterator I = Map.find_as(Lookup); - // Is it in the map? - if (I != Map.end()) + auto I = find(Lookup); + if (I == Map.end()) + Result = create(Ty, V); + else Result = I->first; - - if (!Result) { - // If no preexisting value, create one now... - Result = Create(Ty, V, I); - } + assert(Result && "Unexpected nullptr"); return Result; } @@ -744,23 +591,44 @@ public: } /// Insert the constant into its proper slot. - void insert(ConstantClass *CP) { - Map[CP] = '\0'; - } + void insert(ConstantClass *CP) { Map[CP] = '\0'; } /// Remove this constant from the map void remove(ConstantClass *CP) { - typename MapTy::iterator I = findExistingElement(CP); + typename MapTy::iterator I = Map.find(CP); assert(I != Map.end() && "Constant not found in constant table!"); assert(I->first == CP && "Didn't find correct element?"); Map.erase(I); } - void dump() const { - DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); + ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands, + ConstantClass *CP, Value *From, + Constant *To, unsigned NumUpdated = 0, + unsigned OperandNo = ~0u) { + LookupKey Lookup(CP->getType(), ValType(Operands, CP)); + auto I = find(Lookup); + if (I != Map.end()) + return I->first; + + // Update to the new value. Optimize for the case when we have a single + // operand that we're changing, but handle bulk updates efficiently. + remove(CP); + if (NumUpdated == 1) { + assert(OperandNo < CP->getNumOperands() && "Invalid index"); + assert(CP->getOperand(OperandNo) != To && "I didn't contain From!"); + CP->setOperand(OperandNo, To); + } else { + for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I) + if (CP->getOperand(I) == From) + CP->setOperand(I, To); + } + insert(CP); + return nullptr; } + + void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); } }; -} +} // end namespace llvm #endif diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 87099a6c4e..3576137dd3 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -183,20 +183,22 @@ void LLVMDumpModule(LLVMModuleRef M) { LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, char **ErrorMessage) { - std::string error; - raw_fd_ostream dest(Filename, error, sys::fs::F_Text); - if (!error.empty()) { - *ErrorMessage = strdup(error.c_str()); + std::error_code EC; + raw_fd_ostream dest(Filename, EC, sys::fs::F_Text); + if (EC) { + *ErrorMessage = strdup(EC.message().c_str()); return true; } unwrap(M)->print(dest, nullptr); - if (!error.empty()) { - *ErrorMessage = strdup(error.c_str()); + dest.close(); + + if (dest.has_error()) { + *ErrorMessage = strdup("Error printing to file"); return true; } - dest.flush(); + return false; } @@ -558,8 +560,8 @@ LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) { } void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) { - unwrap<Instruction>(Inst)->setMetadata(KindID, - MD ? unwrap<MDNode>(MD) : nullptr); + unwrap<Instruction>(Inst) + ->setMetadata(KindID, MD ? unwrap<MDNode>(MD) : nullptr); } /*--.. Conversion functions ................................................--*/ @@ -603,6 +605,11 @@ LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index) { return wrap(cast<User>(V)->getOperand(Index)); } +LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index) { + Value *V = unwrap(Val); + return wrap(&cast<User>(V)->getOperandUse(Index)); +} + void LLVMSetOperand(LLVMValueRef Val, unsigned Index, LLVMValueRef Op) { unwrap<User>(Val)->setOperand(Index, unwrap(Op)); } @@ -767,6 +774,27 @@ long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal) { return unwrap<ConstantInt>(ConstantVal)->getSExtValue(); } +double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *LosesInfo) { + ConstantFP *cFP = unwrap<ConstantFP>(ConstantVal) ; + Type *Ty = cFP->getType(); + + if (Ty->isFloatTy()) { + *LosesInfo = false; + return cFP->getValueAPF().convertToFloat(); + } + + if (Ty->isDoubleTy()) { + *LosesInfo = false; + return cFP->getValueAPF().convertToDouble(); + } + + bool APFLosesInfo; + APFloat APF = cFP->getValueAPF(); + APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &APFLosesInfo); + *LosesInfo = APFLosesInfo; + return APF.convertToDouble(); +} + /*--.. Operations on composite constants ...................................--*/ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, @@ -790,11 +818,27 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length, return LLVMConstStringInContext(LLVMGetGlobalContext(), Str, Length, DontNullTerminate); } + +LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx) { + return wrap(static_cast<ConstantDataSequential*>(unwrap(c))->getElementAsConstant(idx)); +} + +LLVMBool LLVMIsConstantString(LLVMValueRef c) { + return static_cast<ConstantDataSequential*>(unwrap(c))->isString(); +} + +const char *LLVMGetAsString(LLVMValueRef c, size_t* Length) { + StringRef str = static_cast<ConstantDataSequential*>(unwrap(c))->getAsString(); + *Length = str.size(); + return str.data(); +} + LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals, unsigned Length) { ArrayRef<Constant*> V(unwrap<Constant>(ConstantVals, Length), Length); return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V)); } + LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, LLVMBool Packed) { return LLVMConstStructInContext(LLVMGetGlobalContext(), ConstantVals, Count, @@ -1859,12 +1903,27 @@ LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst) { return (LLVMIntPredicate)0; } +LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst) { + if (FCmpInst *I = dyn_cast<FCmpInst>(unwrap(Inst))) + return (LLVMRealPredicate)I->getPredicate(); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(unwrap(Inst))) + if (CE->getOpcode() == Instruction::FCmp) + return (LLVMRealPredicate)CE->getPredicate(); + return (LLVMRealPredicate)0; +} + LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst) { if (Instruction *C = dyn_cast<Instruction>(unwrap(Inst))) return map_to_llvmopcode(C->getOpcode()); return (LLVMOpcode)0; } +LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst) { + if (Instruction *C = dyn_cast<Instruction>(unwrap(Inst))) + return wrap(C->clone()); + return nullptr; +} + /*--.. Call and invoke instructions ........................................--*/ unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) { @@ -1926,6 +1985,34 @@ void LLVMSetTailCall(LLVMValueRef Call, LLVMBool isTailCall) { unwrap<CallInst>(Call)->setTailCall(isTailCall); } +/*--.. Operations on terminators ...........................................--*/ + +unsigned LLVMGetNumSuccessors(LLVMValueRef Term) { + return unwrap<TerminatorInst>(Term)->getNumSuccessors(); +} + +LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i) { + return wrap(unwrap<TerminatorInst>(Term)->getSuccessor(i)); +} + +void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block) { + return unwrap<TerminatorInst>(Term)->setSuccessor(i,unwrap(block)); +} + +/*--.. Operations on branch instructions (only) ............................--*/ + +LLVMBool LLVMIsConditional(LLVMValueRef Branch) { + return unwrap<BranchInst>(Branch)->isConditional(); +} + +LLVMValueRef LLVMGetCondition(LLVMValueRef Branch) { + return wrap(unwrap<BranchInst>(Branch)->getCondition()); +} + +void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond) { + return unwrap<BranchInst>(Branch)->setCondition(unwrap(Cond)); +} + /*--.. Operations on switch instructions (only) ............................--*/ LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef Switch) { @@ -2313,7 +2400,7 @@ static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { case LLVMAtomicOrderingSequentiallyConsistent: return SequentiallyConsistent; } - + llvm_unreachable("Invalid LLVMAtomicOrdering value!"); } @@ -2632,10 +2719,9 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange( const char *BufferName, LLVMBool RequiresNullTerminator) { - return wrap(MemoryBuffer::getMemBuffer( - StringRef(InputData, InputDataLength), - StringRef(BufferName), - RequiresNullTerminator)); + return wrap(MemoryBuffer::getMemBuffer(StringRef(InputData, InputDataLength), + StringRef(BufferName), + RequiresNullTerminator).release()); } LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy( @@ -2643,9 +2729,9 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy( size_t InputDataLength, const char *BufferName) { - return wrap(MemoryBuffer::getMemBufferCopy( - StringRef(InputData, InputDataLength), - StringRef(BufferName))); + return wrap( + MemoryBuffer::getMemBufferCopy(StringRef(InputData, InputDataLength), + StringRef(BufferName)).release()); } const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf) { diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 218787c993..4fe2be61b8 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -23,10 +23,29 @@ using namespace llvm; using namespace llvm::dwarf; -static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { - assert((Tag & LLVMDebugVersionMask) == 0 && - "Tag too large for debug encoding!"); - return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion); +namespace { +class HeaderBuilder { + SmallVector<char, 256> Chars; + +public: + explicit HeaderBuilder(Twine T) { T.toVector(Chars); } + HeaderBuilder(const HeaderBuilder &X) : Chars(X.Chars) {} + HeaderBuilder(HeaderBuilder &&X) : Chars(std::move(X.Chars)) {} + + template <class Twineable> HeaderBuilder &concat(Twineable &&X) { + Chars.push_back(0); + Twine(X).toVector(Chars); + return *this; + } + + MDString *get(LLVMContext &Context) const { + return MDString::get(Context, StringRef(Chars.begin(), Chars.size())); + } + + static HeaderBuilder get(unsigned Tag) { + return HeaderBuilder("0x" + Twine::utohexstr(Tag)); + } +}; } DIBuilder::DIBuilder(Module &m) @@ -34,7 +53,6 @@ DIBuilder::DIBuilder(Module &m) TempRetainTypes(nullptr), TempSubprograms(nullptr), TempGVs(nullptr), DeclareFn(nullptr), ValueFn(nullptr) {} -/// finalize - Construct any deferred debug info descriptors. void DIBuilder::finalize() { DIArray Enums = getOrCreateArray(AllEnumTypes); DIType(TempEnumTypes).replaceAllUsesWith(Enums); @@ -46,7 +64,7 @@ void DIBuilder::finalize() { // TrackingVHs back into Values. SmallPtrSet<Value *, 16> RetainSet; for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++) - if (RetainSet.insert(AllRetainTypes[I])) + if (RetainSet.insert(AllRetainTypes[I]).second) RetainValues.push_back(AllRetainTypes[I]); DIArray RetainTypes = getOrCreateArray(RetainValues); DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes); @@ -55,13 +73,10 @@ void DIBuilder::finalize() { DIType(TempSubprograms).replaceAllUsesWith(SPs); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { DISubprogram SP(SPs.getElement(i)); - SmallVector<Value *, 4> Variables; - if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) { - for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii) - Variables.push_back(NMD->getOperand(ii)); - NMD->eraseFromParent(); - } if (MDNode *Temp = SP.getVariablesNodes()) { + SmallVector<Value *, 4> Variables; + for (Value *V : PreservedVariables.lookup(SP)) + Variables.push_back(V); DIArray AV = getOrCreateArray(Variables); DIType(Temp).replaceAllUsesWith(AV); } @@ -77,8 +92,7 @@ void DIBuilder::finalize() { DIType(TempImportedModules).replaceAllUsesWith(IMs); } -/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return -/// N. +/// If N is compile unit return NULL otherwise return N. static MDNode *getNonCompileUnitScope(MDNode *N) { if (DIDescriptor(N).isCompileUnit()) return nullptr; @@ -95,8 +109,6 @@ static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename, return MDNode::get(VMContext, Pair); } -/// createCompileUnit - A CompileUnit provides an anchor for all debugging -/// information generated during this instance of compilation. DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, StringRef Directory, StringRef Producer, bool isOptimized, @@ -110,7 +122,7 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, "Invalid Language tag"); assert(!Filename.empty() && "Unable to create compile unit without filename"); - Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + Value *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)}; TempEnumTypes = MDNode::getTemporary(VMContext, TElts); TempRetainTypes = MDNode::getTemporary(VMContext, TElts); @@ -121,22 +133,18 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, TempImportedModules = MDNode::getTemporary(VMContext, TElts); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), - createFilePathPair(VMContext, Filename, Directory), - ConstantInt::get(Type::getInt32Ty(VMContext), Lang), - MDString::get(VMContext, Producer), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - MDString::get(VMContext, Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer), - TempEnumTypes, - TempRetainTypes, - TempSubprograms, - TempGVs, - TempImportedModules, - MDString::get(VMContext, SplitName), - ConstantInt::get(Type::getInt32Ty(VMContext), Kind) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_compile_unit) + .concat(Lang) + .concat(Producer) + .concat(isOptimized) + .concat(Flags) + .concat(RunTimeVer) + .concat(SplitName) + .concat(Kind) + .get(VMContext), + createFilePathPair(VMContext, Filename, Directory), + TempEnumTypes, TempRetainTypes, TempSubprograms, TempGVs, + TempImportedModules}; MDNode *CUNode = MDNode::get(VMContext, Elts); @@ -158,24 +166,9 @@ createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope Context, Value *NS, unsigned Line, StringRef Name, SmallVectorImpl<TrackingVH<MDNode>> &AllImportedModules) { const MDNode *R; - if (Name.empty()) { - Value *Elts[] = { - GetTagConstant(C, Tag), - Context, - NS, - ConstantInt::get(Type::getInt32Ty(C), Line), - }; - R = MDNode::get(C, Elts); - } else { - Value *Elts[] = { - GetTagConstant(C, Tag), - Context, - NS, - ConstantInt::get(Type::getInt32Ty(C), Line), - MDString::get(C, Name) - }; - R = MDNode::get(C, Elts); - } + Value *Elts[] = {HeaderBuilder::get(Tag).concat(Line).concat(Name).get(C), + Context, NS}; + R = MDNode::get(C, Elts); DIImportedEntity M(R); assert(M.Verify() && "Imported module should be valid"); AllImportedModules.push_back(TrackingVH<MDNode>(M)); @@ -197,10 +190,13 @@ DIImportedEntity DIBuilder::createImportedModule(DIScope Context, } DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context, - DIScope Decl, + DIDescriptor Decl, unsigned Line, StringRef Name) { + // Make sure to use the unique identifier based metadata reference for + // types that have one. + Value *V = Decl.isType() ? static_cast<Value*>(DIType(Decl).getRef()) : Decl; return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration, - Context, Decl.getRef(), Line, Name, + Context, V, Line, Name, AllImportedModules); } @@ -211,54 +207,44 @@ DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context, Context, Imp, Line, Name, AllImportedModules); } -/// createFile - Create a file descriptor to hold debugging information -/// for a file. DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_file_type), - createFilePathPair(VMContext, Filename, Directory) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_file_type).get(VMContext), + createFilePathPair(VMContext, Filename, Directory)}; return DIFile(MDNode::get(VMContext, Elts)); } -/// createEnumerator - Create a single enumerator value. 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), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt64Ty(VMContext), Val) - }; + HeaderBuilder::get(dwarf::DW_TAG_enumerator).concat(Name).concat(Val).get( + VMContext)}; return DIEnumerator(MDNode::get(VMContext, Elts)); } -/// \brief Create a DWARF unspecified type. DIBasicType DIBuilder::createUnspecifiedType(StringRef Name) { assert(!Name.empty() && "Unable to create type without name"); // 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), - nullptr, // Filename - nullptr, // Unused - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; - ConstantInt::get(Type::getInt32Ty(VMContext), 0) // Encoding + HeaderBuilder::get(dwarf::DW_TAG_unspecified_type) + .concat(Name) + .concat(0) + .concat(0) + .concat(0) + .concat(0) + .concat(0) + .concat(0) + .get(VMContext), + nullptr, // Filename + nullptr // Unused }; 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 DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding) { @@ -266,160 +252,139 @@ DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, // Basic types are encoded in DIBasicType format. Line number, filename, // offset and flags are always empty here. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_base_type), - nullptr, // File/directory name - nullptr, // Unused - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) + HeaderBuilder::get(dwarf::DW_TAG_base_type) + .concat(Name) + .concat(0) // Line + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .concat(Encoding) + .get(VMContext), + nullptr, // Filename + nullptr // Unused }; return DIBasicType(MDNode::get(VMContext, Elts)); } -/// createQualifiedType - Create debugging information entry for a qualified -/// type, e.g. 'const int'. DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { // Qualified types are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - nullptr, // Filename - nullptr, // Unused - MDString::get(VMContext, StringRef()), // Empty name. - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - FromTy.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(Tag) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // Unused + FromTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createPointerType - Create debugging information entry for a pointer. DIDerivedType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits, StringRef Name) { // Pointer types are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), - nullptr, // Filename - nullptr, // Unused - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - PointeeTy.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_pointer_type) + .concat(Name) + .concat(0) // Line + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // Unused + PointeeTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } 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), - nullptr, // Filename - nullptr, // Unused - nullptr, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - PointeeTy.getRef(), - Base.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_ptr_to_member_type) + .concat(StringRef()) + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // Unused + PointeeTy.getRef(), Base.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createReferenceType - Create debugging information entry for a reference -/// type. DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { assert(RTy.isType() && "Unable to create reference type"); // References are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - nullptr, // Filename - nullptr, // TheCU, - nullptr, // Name - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - RTy.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(Tag) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // TheCU, + RTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createTypedef - Create debugging information entry for a typedef. DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo, DIDescriptor Context) { // typedefs are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_typedef), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - Ty.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_typedef) + .concat(Name) + .concat(LineNo) + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Context)).getRef(), + Ty.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createFriend - Create debugging information entry for a 'friend'. DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { // typedefs are encoded in DIDerivedType format. assert(Ty.isType() && "Invalid type!"); assert(FriendTy.isType() && "Invalid friend type!"); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_friend), - nullptr, - Ty.getRef(), - nullptr, // Name - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - FriendTy.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_friend) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, Ty.getRef(), FriendTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createInheritance - Create debugging information entry to establish -/// inheritance relationship between two types. DIDerivedType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags) { assert(Ty.isType() && "Unable to create inheritance"); // TAG_inheritance is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), - nullptr, - Ty.getRef(), - nullptr, // Name - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), BaseOffset), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - BaseTy.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_inheritance) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(BaseOffset) + .concat(Flags) + .get(VMContext), + nullptr, Ty.getRef(), BaseTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createMemberType - Create debugging information entry for a member. DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -427,76 +392,41 @@ DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, uint64_t OffsetInBits, unsigned Flags, DIType Ty) { // TAG_member is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty.getRef() - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(OffsetInBits) + .concat(Flags) + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Scope)).getRef(), + Ty.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createStaticMemberType - Create debugging information entry for a -/// C++ static data member. -DIDerivedType -DIBuilder::createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - DIType Ty, unsigned Flags, - llvm::Value *Val) { +DIDerivedType DIBuilder::createStaticMemberType(DIDescriptor Scope, + StringRef Name, DIFile File, + unsigned LineNumber, DIType Ty, + unsigned Flags, + llvm::Constant *Val) { // TAG_member is encoded in DIDerivedType format. Flags |= DIDescriptor::FlagStaticMember; - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty.getRef(), - Val - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member) + .concat(Name) + .concat(LineNumber) + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(Flags) + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Scope)).getRef(), Ty.getRef(), + Val}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createObjCIVar - Create debugging information entry for Objective-C -/// instance variable. -DIDerivedType -DIBuilder::createObjCIVar(StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, DIType Ty, - StringRef PropertyName, StringRef GetterName, - StringRef SetterName, unsigned PropertyAttributes) { - // TAG_member is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - getNonCompileUnitScope(File), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty, - MDString::get(VMContext, PropertyName), - MDString::get(VMContext, GetterName), - MDString::get(VMContext, SetterName), - ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes) - }; - return DIDerivedType(MDNode::get(VMContext, Elts)); -} - -/// createObjCIVar - Create debugging information entry for Objective-C -/// instance variable. DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -504,88 +434,66 @@ DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File, uint64_t OffsetInBits, unsigned Flags, DIType Ty, MDNode *PropertyNode) { // TAG_member is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - getNonCompileUnitScope(File), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty, - PropertyNode - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(OffsetInBits) + .concat(Flags) + .get(VMContext), + File.getFileNode(), getNonCompileUnitScope(File), Ty, + PropertyNode}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createObjCProperty - Create debugging information entry for Objective-C -/// property. DIObjCProperty DIBuilder::createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber, StringRef GetterName, StringRef SetterName, unsigned PropertyAttributes, DIType Ty) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_APPLE_property), - MDString::get(VMContext, Name), - File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - MDString::get(VMContext, GetterName), - MDString::get(VMContext, SetterName), - ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes), - Ty - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_APPLE_property) + .concat(Name) + .concat(LineNumber) + .concat(GetterName) + .concat(SetterName) + .concat(PropertyAttributes) + .get(VMContext), + File, Ty}; return DIObjCProperty(MDNode::get(VMContext, Elts)); } -/// createTemplateTypeParameter - Create debugging information for template -/// type parameter. DITemplateTypeParameter DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, DIType Ty, MDNode *File, unsigned LineNo, unsigned ColumnNo) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - Ty.getRef(), - File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_template_type_parameter) + .concat(Name) + .concat(LineNo) + .concat(ColumnNo) + .get(VMContext), + DIScope(getNonCompileUnitScope(Context)).getRef(), + Ty.getRef(), File}; return DITemplateTypeParameter(MDNode::get(VMContext, Elts)); } -DITemplateValueParameter -DIBuilder::createTemplateValueParameter(unsigned Tag, DIDescriptor Context, - StringRef Name, DIType Ty, - Value *Val, MDNode *File, - unsigned LineNo, - unsigned ColumnNo) { +static DITemplateValueParameter createTemplateValueParameterHelper( + LLVMContext &VMContext, unsigned Tag, DIDescriptor Context, StringRef Name, + DIType Ty, Value *Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) { Value *Elts[] = { - GetTagConstant(VMContext, Tag), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - Ty.getRef(), - Val, - File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) - }; + HeaderBuilder::get(Tag).concat(Name).concat(LineNo).concat(ColumnNo).get( + VMContext), + DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), Val, + File}; 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); + DIType Ty, Constant *Val, MDNode *File, + unsigned LineNo, unsigned ColumnNo) { + return createTemplateValueParameterHelper( + VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty, Val, + File, LineNo, ColumnNo); } DITemplateValueParameter @@ -593,8 +501,8 @@ 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, + return createTemplateValueParameterHelper( + VMContext, dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty, MDString::get(VMContext, Val), File, LineNo, ColumnNo); } @@ -603,12 +511,11 @@ 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); + return createTemplateValueParameterHelper( + VMContext, 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, uint64_t SizeInBits, @@ -623,23 +530,19 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, "createClassType should be called with a valid Context"); // TAG_class_type is encoded in DICompositeType format. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_class_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getRef(), - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - VTableHolder.getRef(), - TemplateParams, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + HeaderBuilder::get(dwarf::DW_TAG_class_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(OffsetInBits) + .concat(Flags) + .concat(0) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), + DerivedFrom.getRef(), Elements, VTableHolder.getRef(), TemplateParams, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType R(MDNode::get(VMContext, Elts)); assert(R.isCompositeType() && "createClassType should return a DICompositeType"); @@ -648,7 +551,6 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, return R; } -/// createStructType - Create debugging information entry for a struct. DICompositeType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, DIFile File, unsigned LineNumber, @@ -661,23 +563,19 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context, StringRef UniqueIdentifier) { // TAG_structure_type is encoded in DICompositeType format. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_structure_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getRef(), - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), - VTableHolder.getRef(), - nullptr, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + HeaderBuilder::get(dwarf::DW_TAG_structure_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) + .concat(Flags) + .concat(RunTimeLang) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), + DerivedFrom.getRef(), Elements, VTableHolder.getRef(), nullptr, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType R(MDNode::get(VMContext, Elts)); assert(R.isCompositeType() && "createStructType should return a DICompositeType"); @@ -686,7 +584,6 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context, return R; } -/// createUnionType - Create debugging information entry for an union. DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -696,79 +593,64 @@ DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, StringRef UniqueIdentifier) { // TAG_union_type is encoded in DICompositeType format. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_union_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - nullptr, - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), - nullptr, - nullptr, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + HeaderBuilder::get(dwarf::DW_TAG_union_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(Flags) + .concat(RunTimeLang) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), + nullptr, Elements, nullptr, nullptr, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType R(MDNode::get(VMContext, Elts)); if (!UniqueIdentifier.empty()) retainType(R); return R; } -/// createSubroutineType - Create subroutine type. -DICompositeType DIBuilder::createSubroutineType(DIFile File, - DIArray ParameterTypes, - unsigned Flags) { +DISubroutineType DIBuilder::createSubroutineType(DIFile File, + DITypeArray ParameterTypes, + unsigned Flags) { // TAG_subroutine_type is encoded in DICompositeType format. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - nullptr, - MDString::get(VMContext, ""), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), // Flags - nullptr, - ParameterTypes, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - nullptr // Type Identifer + HeaderBuilder::get(dwarf::DW_TAG_subroutine_type) + .concat(StringRef()) + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(Flags) // Flags + .concat(0) + .get(VMContext), + nullptr, nullptr, nullptr, ParameterTypes, nullptr, nullptr, + nullptr // Type Identifer }; - return DICompositeType(MDNode::get(VMContext, Elts)); + return DISubroutineType(MDNode::get(VMContext, Elts)); } -/// createEnumerationType - Create debugging information entry for an -/// enumeration. DICompositeType DIBuilder::createEnumerationType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, StringRef UniqueIdentifier) { // TAG_enumeration_type is encoded in DICompositeType format. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - UnderlyingType.getRef(), - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + HeaderBuilder::get(dwarf::DW_TAG_enumeration_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .concat(0) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), + UnderlyingType.getRef(), Elements, nullptr, nullptr, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType CTy(MDNode::get(VMContext, Elts)); AllEnumTypes.push_back(CTy); if (!UniqueIdentifier.empty()) @@ -776,114 +658,96 @@ DICompositeType DIBuilder::createEnumerationType( return CTy; } -/// createArrayType - Create debugging information entry for an array. DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // TAG_array_type is encoded in DICompositeType format. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_array_type), - nullptr, // Filename/Directory, - nullptr, // Unused - MDString::get(VMContext, ""), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), Size), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - Ty.getRef(), - Subscripts, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - nullptr // Type Identifer + HeaderBuilder::get(dwarf::DW_TAG_array_type) + .concat(StringRef()) + .concat(0) // Line + .concat(Size) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .concat(0) + .get(VMContext), + nullptr, // Filename/Directory, + nullptr, // Unused + Ty.getRef(), Subscripts, nullptr, nullptr, + nullptr // Type Identifer }; return DICompositeType(MDNode::get(VMContext, Elts)); } -/// createVectorType - Create debugging information entry for a vector. DICompositeType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // A vector is an array type with the FlagVector flag applied. Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_array_type), - nullptr, // Filename/Directory, - nullptr, // Unused - MDString::get(VMContext, ""), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), Size), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), DIType::FlagVector), - Ty.getRef(), - Subscripts, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - nullptr // Type Identifer + HeaderBuilder::get(dwarf::DW_TAG_array_type) + .concat("") + .concat(0) // Line + .concat(Size) + .concat(AlignInBits) + .concat(0) // Offset + .concat(DIType::FlagVector) + .concat(0) + .get(VMContext), + nullptr, // Filename/Directory, + nullptr, // Unused + Ty.getRef(), Subscripts, nullptr, nullptr, + nullptr // Type Identifer }; return DICompositeType(MDNode::get(VMContext, Elts)); } -/// createArtificialType - Create a new DIType with "artificial" flag set. -DIType DIBuilder::createArtificialType(DIType Ty) { - if (Ty.isArtificial()) - return Ty; +static HeaderBuilder setTypeFlagsInHeader(StringRef Header, + unsigned FlagsToSet) { + DIHeaderFieldIterator I(Header); + std::advance(I, 6); + unsigned Flags; + if (I->getAsInteger(0, Flags)) + Flags = 0; + Flags |= FlagsToSet; + + return HeaderBuilder(Twine(I.getPrefix())).concat(Flags).concat( + I.getSuffix()); +} + +static DIType createTypeWithFlags(LLVMContext &Context, DIType Ty, + unsigned FlagsToSet) { SmallVector<Value *, 9> Elts; MDNode *N = Ty; - assert (N && "Unexpected input DIType!"); - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) - Elts.push_back(N->getOperand(i)); - - unsigned CurFlags = Ty.getFlags(); - CurFlags = CurFlags | DIType::FlagArtificial; + assert(N && "Unexpected input DIType!"); + // Update header field. + Elts.push_back(setTypeFlagsInHeader(Ty.getHeader(), FlagsToSet).get(Context)); + for (unsigned I = 1, E = N->getNumOperands(); I != E; ++I) + Elts.push_back(N->getOperand(I)); - // Flags are stored at this slot. - // FIXME: Add an enum for this magic value. - Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); + return DIType(MDNode::get(Context, Elts)); +} - return DIType(MDNode::get(VMContext, Elts)); +DIType DIBuilder::createArtificialType(DIType Ty) { + if (Ty.isArtificial()) + return Ty; + return createTypeWithFlags(VMContext, Ty, DIType::FlagArtificial); } -/// createObjectPointerType - Create a new type with both the object pointer -/// and artificial flags set. DIType DIBuilder::createObjectPointerType(DIType Ty) { if (Ty.isObjectPointer()) return Ty; - - SmallVector<Value *, 9> Elts; - MDNode *N = Ty; - assert (N && "Unexpected input DIType!"); - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) - Elts.push_back(N->getOperand(i)); - - unsigned CurFlags = Ty.getFlags(); - CurFlags = CurFlags | (DIType::FlagObjectPointer | DIType::FlagArtificial); - - // Flags are stored at this slot. - // FIXME: Add an enum for this magic value. - Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); - - return DIType(MDNode::get(VMContext, Elts)); + unsigned Flags = DIType::FlagObjectPointer | DIType::FlagArtificial; + return createTypeWithFlags(VMContext, Ty, Flags); } -/// retainType - Retain DIType in a module even if it is not referenced -/// through debug info anchors. void DIBuilder::retainType(DIType T) { AllRetainTypes.push_back(TrackingVH<MDNode>(T)); } -/// createUnspecifiedParameter - Create unspeicified type descriptor -/// for the subroutine type. -DIDescriptor DIBuilder::createUnspecifiedParameter() { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) - }; - return DIDescriptor(MDNode::get(VMContext, Elts)); +DIBasicType DIBuilder::createUnspecifiedParameter() { + return DIBasicType(); } -/// createForwardDecl - Create a temporary forward-declared type that -/// can be RAUW'd if the full type is seen. DICompositeType DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang, @@ -891,23 +755,20 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, StringRef UniqueIdentifier) { // Create a temporary MDNode. Value *Elts[] = { - GetTagConstant(VMContext, Tag), - F.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), Line), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl), - nullptr, - DIArray(), - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - nullptr, - nullptr, //TemplateParams - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + HeaderBuilder::get(Tag) + .concat(Name) + .concat(Line) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(DIDescriptor::FlagFwdDecl) + .concat(RuntimeLang) + .get(VMContext), + F.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), nullptr, + DIArray(), nullptr, + nullptr, // TemplateParams + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; MDNode *Node = MDNode::get(VMContext, Elts); DICompositeType RetTy(Node); assert(RetTy.isCompositeType() && @@ -917,123 +778,102 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, return RetTy; } -/// createForwardDecl - Create a temporary forward-declared type that -/// can be RAUW'd if the full type is seen. DICompositeType DIBuilder::createReplaceableForwardDecl( unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, StringRef UniqueIdentifier) { // Create a temporary MDNode. Value *Elts[] = { - GetTagConstant(VMContext, Tag), - F.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), Line), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl), - nullptr, - DIArray(), - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - nullptr, - nullptr, //TemplateParams - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + HeaderBuilder::get(Tag) + .concat(Name) + .concat(Line) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(DIDescriptor::FlagFwdDecl) + .concat(RuntimeLang) + .get(VMContext), + F.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), nullptr, + DIArray(), nullptr, + nullptr, // TemplateParams + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; MDNode *Node = MDNode::getTemporary(VMContext, Elts); DICompositeType RetTy(Node); assert(RetTy.isCompositeType() && - "createForwardDecl result should be a DIType"); + "createReplaceableForwardDecl result should be a DIType"); if (!UniqueIdentifier.empty()) retainType(RetTy); return RetTy; } -/// getOrCreateArray - Get a DIArray, create one if required. DIArray DIBuilder::getOrCreateArray(ArrayRef<Value *> Elements) { return DIArray(MDNode::get(VMContext, Elements)); } -/// getOrCreateSubrange - Create a descriptor for a value range. This -/// implicitly uniques the values returned. +DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef<Value *> Elements) { + SmallVector<llvm::Value *, 16> Elts; + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { + if (Elements[i] && isa<MDNode>(Elements[i])) + Elts.push_back(DIType(cast<MDNode>(Elements[i])).getRef()); + else + Elts.push_back(Elements[i]); + } + return DITypeArray(MDNode::get(VMContext, Elts)); +} + DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type), - ConstantInt::get(Type::getInt64Ty(VMContext), Lo), - ConstantInt::get(Type::getInt64Ty(VMContext), Count) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subrange_type) + .concat(Lo) + .concat(Count) + .get(VMContext)}; return DISubrange(MDNode::get(VMContext, Elts)); } -/// \brief Create a new descriptor for the specified global. -DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, - StringRef LinkageName, - DIFile F, unsigned LineNumber, - DITypeRef Ty, bool isLocalToUnit, - Value *Val) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_variable), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - nullptr, // TheCU, - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ - Val, - DIDescriptor() - }; - MDNode *Node = MDNode::get(VMContext, Elts); - AllGVs.push_back(Node); - return DIGlobalVariable(Node); -} - -/// \brief Create a new descriptor for the specified global. -DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, DIFile F, - unsigned LineNumber, - DITypeRef Ty, - bool isLocalToUnit, - Value *Val) { - return createGlobalVariable(Name, Name, F, LineNumber, Ty, isLocalToUnit, - Val); -} - -/// createStaticVariable - Create a new descriptor for the specified static -/// variable. -DIGlobalVariable DIBuilder::createStaticVariable(DIDescriptor Context, - StringRef Name, - StringRef LinkageName, - DIFile F, unsigned LineNumber, - DITypeRef Ty, - bool isLocalToUnit, - Value *Val, MDNode *Decl) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_variable), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - getNonCompileUnitScope(Context), - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ - Val, - DIDescriptor(Decl) - }; - MDNode *Node = MDNode::get(VMContext, Elts); - AllGVs.push_back(Node); - return DIGlobalVariable(Node); +static DIGlobalVariable createGlobalVariableHelper( + LLVMContext &VMContext, DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile F, unsigned LineNumber, DITypeRef Ty, + bool isLocalToUnit, Constant *Val, MDNode *Decl, bool isDefinition, + std::function<MDNode *(ArrayRef<Value *>)> CreateFunc) { + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_variable) + .concat(Name) + .concat(Name) + .concat(LinkageName) + .concat(LineNumber) + .concat(isLocalToUnit) + .concat(isDefinition) + .get(VMContext), + DIScope(getNonCompileUnitScope(Context)).getRef(), F, Ty, Val, + DIDescriptor(Decl)}; + + return DIGlobalVariable(CreateFunc(Elts)); +} + +DIGlobalVariable DIBuilder::createGlobalVariable( + DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, + unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val, + MDNode *Decl) { + return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F, + LineNumber, Ty, isLocalToUnit, Val, Decl, true, + [&] (ArrayRef<Value *> Elts) -> MDNode * { + MDNode *Node = MDNode::get(VMContext, Elts); + AllGVs.push_back(Node); + return Node; + }); +} + +DIGlobalVariable DIBuilder::createTempGlobalVariableFwdDecl( + DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, + unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val, + MDNode *Decl) { + return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F, + LineNumber, Ty, isLocalToUnit, Val, Decl, false, + [&] (ArrayRef<Value *> Elts) { + return MDNode::getTemporary(VMContext, Elts); + }); } -/// createVariable - Create a new descriptor for the specified variable. DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DITypeRef Ty, @@ -1042,24 +882,20 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, DIDescriptor Context(getNonCompileUnitScope(Scope)); assert((!Context || Context.isScope()) && "createLocalVariable should be called with a valid Context"); - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - getNonCompileUnitScope(Scope), - MDString::get(VMContext, Name), - File, - ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Constant::getNullValue(Type::getInt32Ty(VMContext)) - }; + Value *Elts[] = {HeaderBuilder::get(Tag) + .concat(Name) + .concat(LineNo | (ArgNo << 24)) + .concat(Flags) + .get(VMContext), + getNonCompileUnitScope(Scope), File, Ty}; MDNode *Node = MDNode::get(VMContext, Elts); if (AlwaysPreserve) { // The optimizer may remove local variable. If there is an interest // to preserve variable info in such situation then stash it in a // named mdnode. DISubprogram Fn(getDISubprogram(Scope)); - NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); - FnLocals->addOperand(Node); + assert(Fn && "Missing subprogram for local variable"); + PreservedVariables[Fn].push_back(Node); } DIVariable RetVar(Node); assert(RetVar.isVariable() && @@ -1067,33 +903,20 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, return RetVar; } -/// createComplexVariable - Create a new descriptor for the specified variable -/// which has a complex address expression for its address. -DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIFile F, - unsigned LineNo, - DITypeRef Ty, - ArrayRef<Value *> Addr, - unsigned ArgNo) { - assert(Addr.size() > 0 && "complex address is empty"); - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - getNonCompileUnitScope(Scope), - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), - (LineNo | (ArgNo << 24))), - Ty, - Constant::getNullValue(Type::getInt32Ty(VMContext)), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - MDNode::get(VMContext, Addr) - }; - return DIVariable(MDNode::get(VMContext, Elts)); +DIExpression DIBuilder::createExpression(ArrayRef<int64_t> Addr) { + auto Header = HeaderBuilder::get(DW_TAG_expression); + for (int64_t I : Addr) + Header.concat(I); + Value *Elts[] = {Header.get(VMContext)}; + return DIExpression(MDNode::get(VMContext, Elts)); +} + +DIExpression DIBuilder::createPieceExpression(unsigned OffsetInBytes, + unsigned SizeInBytes) { + int64_t Addr[] = {dwarf::DW_OP_piece, OffsetInBytes, SizeInBytes}; + return createExpression(Addr); } -/// createFunction - Create a new descriptor for the specified function. -/// FIXME: this is added for dragonegg. Once we update dragonegg -/// to call resolve function, this will be removed. DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, @@ -1109,7 +932,39 @@ DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name, Flags, isOptimized, Fn, TParams, Decl); } -/// createFunction - Create a new descriptor for the specified function. +static DISubprogram +createFunctionHelper(LLVMContext &VMContext, DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, unsigned LineNo, + DICompositeType Ty, bool isLocalToUnit, bool isDefinition, + unsigned ScopeLine, unsigned Flags, bool isOptimized, + Function *Fn, MDNode *TParams, MDNode *Decl, MDNode *Vars, + std::function<MDNode *(ArrayRef<Value *>)> CreateFunc) { + assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type && + "function types should be subroutines"); + Value *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_subprogram) + .concat(Name) + .concat(Name) + .concat(LinkageName) + .concat(LineNo) + .concat(isLocalToUnit) + .concat(isDefinition) + .concat(0) + .concat(0) + .concat(Flags) + .concat(isOptimized) + .concat(ScopeLine) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), Ty, + nullptr, Fn, TParams, Decl, Vars}; + + DISubprogram S(CreateFunc(Elts)); + assert(S.isSubprogram() && + "createFunction should return a valid DISubprogram"); + return S; +} + + DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, @@ -1117,43 +972,36 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name, unsigned ScopeLine, unsigned Flags, bool isOptimized, Function *Fn, MDNode *TParams, MDNode *Decl) { - assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type && - "function types should be subroutines"); - Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn, - TParams, - Decl, - MDNode::getTemporary(VMContext, TElts), - ConstantInt::get(Type::getInt32Ty(VMContext), ScopeLine) - }; - MDNode *Node = MDNode::get(VMContext, Elts); + return createFunctionHelper(VMContext, Context, Name, LinkageName, File, + LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, + Flags, isOptimized, Fn, TParams, Decl, + MDNode::getTemporary(VMContext, None), + [&] (ArrayRef<Value *> Elts) -> MDNode *{ + MDNode *Node = MDNode::get(VMContext, Elts); + // Create a named metadata so that we + // do not lose this mdnode. + if (isDefinition) + AllSubprograms.push_back(Node); + return Node; + }); +} - // Create a named metadata so that we do not lose this mdnode. - if (isDefinition) - AllSubprograms.push_back(Node); - DISubprogram S(Node); - assert(S.isSubprogram() && - "createFunction should return a valid DISubprogram"); - return S; +DISubprogram +DIBuilder::createTempFunctionFwdDecl(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, + unsigned LineNo, DICompositeType Ty, + bool isLocalToUnit, bool isDefinition, + unsigned ScopeLine, unsigned Flags, + bool isOptimized, Function *Fn, + MDNode *TParams, MDNode *Decl) { + return createFunctionHelper(VMContext, Context, Name, LinkageName, File, + LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, + Flags, isOptimized, Fn, TParams, Decl, nullptr, + [&] (ArrayRef<Value *> Elts) { + return MDNode::getTemporary(VMContext, Elts); + }); } -/// createMethod - Create a new descriptor for the specified C++ method. DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, unsigned LineNo, DICompositeType Ty, @@ -1167,29 +1015,22 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, assert(getNonCompileUnitScope(Context) && "Methods should have both a Context and a context that isn't " "the compile unit."); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), - F.getFileNode(), - DIScope(Context).getRef(), - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), VK), - ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), - VTableHolder.getRef(), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn, - TParam, - Constant::getNullValue(Type::getInt32Ty(VMContext)), - nullptr, - // FIXME: Do we want to use different scope/lines? - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram) + .concat(Name) + .concat(Name) + .concat(LinkageName) + .concat(LineNo) + .concat(isLocalToUnit) + .concat(isDefinition) + .concat(VK) + .concat(VIndex) + .concat(Flags) + .concat(isOptimized) + .concat(LineNo) + // FIXME: Do we want to use different scope/lines? + .get(VMContext), + F.getFileNode(), DIScope(Context).getRef(), Ty, + VTableHolder.getRef(), Fn, TParam, nullptr, nullptr}; MDNode *Node = MDNode::get(VMContext, Elts); if (isDefinition) AllSubprograms.push_back(Node); @@ -1198,32 +1039,26 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, return S; } -/// createNameSpace - This creates new descriptor for a namespace -/// with the specified parent scope. DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_namespace), - File.getFileNode(), - getNonCompileUnitScope(Scope), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_namespace) + .concat(Name) + .concat(LineNo) + .get(VMContext), + File.getFileNode(), getNonCompileUnitScope(Scope)}; DINameSpace R(MDNode::get(VMContext, Elts)); assert(R.Verify() && "createNameSpace should return a verifiable DINameSpace"); return R; } -/// createLexicalBlockFile - This creates a new MDNode that encapsulates -/// an existing scope with a new filename. DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, - DIFile File) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), - File.getFileNode(), - Scope - }; + DIFile File, + unsigned Discriminator) { + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block) + .concat(Discriminator) + .get(VMContext), + File.getFileNode(), Scope}; DILexicalBlockFile R(MDNode::get(VMContext, Elts)); assert( R.Verify() && @@ -1232,8 +1067,7 @@ DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, } DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col, - unsigned Discriminator) { + unsigned Line, unsigned Col) { // FIXME: This isn't thread safe nor the right way to defeat MDNode uniquing. // I believe the right way is to have a self-referential element in the node. // Also: why do we bother with line/column - they're not used and the @@ -1243,23 +1077,20 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, // 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), - File.getFileNode(), - getNonCompileUnitScope(Scope), - ConstantInt::get(Type::getInt32Ty(VMContext), Line), - ConstantInt::get(Type::getInt32Ty(VMContext), Col), - ConstantInt::get(Type::getInt32Ty(VMContext), Discriminator), - ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) - }; + Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block) + .concat(Line) + .concat(Col) + .concat(unique_id++) + .get(VMContext), + File.getFileNode(), getNonCompileUnitScope(Scope)}; DILexicalBlock R(MDNode::get(VMContext, Elts)); assert(R.Verify() && "createLexicalBlock should return a verifiable DILexicalBlock"); return R; } -/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + DIExpression Expr, Instruction *InsertBefore) { assert(Storage && "no storage passed to dbg.declare"); assert(VarInfo.isVariable() && @@ -1267,12 +1098,12 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; + Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr}; return CallInst::Create(DeclareFn, Args, "", InsertBefore); } -/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + DIExpression Expr, BasicBlock *InsertAtEnd) { assert(Storage && "no storage passed to dbg.declare"); assert(VarInfo.isVariable() && @@ -1280,7 +1111,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; + Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr}; // If this block already has a terminator then insert this intrinsic // before the terminator. @@ -1290,9 +1121,9 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, return CallInst::Create(DeclareFn, Args, "", InsertAtEnd); } -/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, + DIExpression Expr, Instruction *InsertBefore) { assert(V && "no value passed to dbg.value"); assert(VarInfo.isVariable() && @@ -1300,15 +1131,15 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Args[] = { MDNode::get(V->getContext(), V), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - VarInfo }; + Value *Args[] = {MDNode::get(V->getContext(), V), + ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), + VarInfo, Expr}; return CallInst::Create(ValueFn, Args, "", InsertBefore); } -/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, + DIExpression Expr, BasicBlock *InsertAtEnd) { assert(V && "no value passed to dbg.value"); assert(VarInfo.isVariable() && @@ -1316,8 +1147,8 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Args[] = { MDNode::get(V->getContext(), V), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - VarInfo }; + Value *Args[] = {MDNode::get(V->getContext(), V), + ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), + VarInfo, Expr}; return CallInst::Create(ValueFn, Args, "", InsertAtEnd); } diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index dea05fbef4..8a057f552a 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -55,7 +55,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { // Add padding if necessary to align the data element properly. if ((StructSize & (TyAlign-1)) != 0) - StructSize = DataLayout::RoundUpAlignment(StructSize, TyAlign); + StructSize = RoundUpToAlignment(StructSize, TyAlign); // Keep track of maximum alignment constraint. StructAlignment = std::max(TyAlign, StructAlignment); @@ -70,7 +70,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { // Add padding to the end of the struct so that it could be put in an array // and all array elements would be aligned correctly. if ((StructSize & (StructAlignment-1)) != 0) - StructSize = DataLayout::RoundUpAlignment(StructSize, StructAlignment); + StructSize = RoundUpToAlignment(StructSize, StructAlignment); } @@ -179,7 +179,7 @@ void DataLayout::reset(StringRef Desc) { clear(); LayoutMap = nullptr; - LittleEndian = false; + BigEndian = false; StackNaturalAlign = 0; ManglingMode = MM_None; @@ -239,10 +239,10 @@ void DataLayout::parseSpecifier(StringRef Desc) { // FIXME: remove this on LLVM 4.0. break; case 'E': - LittleEndian = false; + BigEndian = true; break; case 'e': - LittleEndian = true; + BigEndian = false; break; case 'p': { // Address space. @@ -345,6 +345,10 @@ void DataLayout::parseSpecifier(StringRef Desc) { } DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) { + init(M); +} + +void DataLayout::init(const Module *M) { const DataLayout *Other = M->getDataLayout(); if (Other) *this = *Other; @@ -353,7 +357,7 @@ DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) { } bool DataLayout::operator==(const DataLayout &Other) const { - bool Ret = LittleEndian == Other.LittleEndian && + bool Ret = BigEndian == Other.BigEndian && StackNaturalAlign == Other.StackNaturalAlign && ManglingMode == Other.ManglingMode && LegalIntWidths == Other.LegalIntWidths && @@ -522,7 +526,7 @@ std::string DataLayout::getStringRepresentation() const { std::string Result; raw_string_ostream OS(Result); - OS << (LittleEndian ? "e" : "E"); + OS << (BigEndian ? "E" : "e"); switch (ManglingMode) { case MM_None: @@ -637,7 +641,7 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { ? getPointerABIAlignment(0) : getPointerPrefAlignment(0)); case Type::PointerTyID: { - unsigned AS = dyn_cast<PointerType>(Ty)->getAddressSpace(); + unsigned AS = cast<PointerType>(Ty)->getAddressSpace(); return (abi_or_pref ? getPointerABIAlignment(AS) : getPointerPrefAlignment(AS)); @@ -796,17 +800,17 @@ unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const { } DataLayoutPass::DataLayoutPass() : ImmutablePass(ID), DL("") { - report_fatal_error("Bad DataLayoutPass ctor used. Tool did not specify a " - "DataLayout to use?"); + initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); } DataLayoutPass::~DataLayoutPass() {} -DataLayoutPass::DataLayoutPass(const DataLayout &DL) - : ImmutablePass(ID), DL(DL) { - initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); +bool DataLayoutPass::doInitialization(Module &M) { + DL.init(&M); + return false; } -DataLayoutPass::DataLayoutPass(const Module *M) : ImmutablePass(ID), DL(M) { - initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); +bool DataLayoutPass::doFinalization(Module &M) { + DL.reset(""); + return false; } diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 5e39b242db..bb5161dcb9 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -46,10 +47,9 @@ bool DIDescriptor::Verify() const { DILexicalBlockFile(DbgNode).Verify() || DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() || DIObjCProperty(DbgNode).Verify() || - DIUnspecifiedParameter(DbgNode).Verify() || DITemplateTypeParameter(DbgNode).Verify() || DITemplateValueParameter(DbgNode).Verify() || - DIImportedEntity(DbgNode).Verify()); + DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify()); } static Value *getField(const MDNode *DbgNode, unsigned Elt) { @@ -138,25 +138,53 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { } } -uint64_t DIVariable::getAddrElement(unsigned Idx) const { - DIDescriptor ComplexExpr = getDescriptorField(8); - if (Idx < ComplexExpr->getNumOperands()) - if (auto *CI = dyn_cast_or_null<ConstantInt>(ComplexExpr->getOperand(Idx))) - return CI->getZExtValue(); +static unsigned DIVariableInlinedAtIndex = 4; +MDNode *DIVariable::getInlinedAt() const { + return getNodeField(DbgNode, DIVariableInlinedAtIndex); +} - assert(false && "non-existing complex address element requested"); - return 0; +/// \brief Return the size reported by the variable's type. +unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) { + DIType Ty = getType().resolve(Map); + // Follow derived types until we reach a type that + // reports back a size. + while (Ty.isDerivedType() && !Ty.getSizeInBits()) { + DIDerivedType DT(&*Ty); + Ty = DT.getTypeDerivedFrom().resolve(Map); + } + assert(Ty.getSizeInBits() && "type with size 0"); + return Ty.getSizeInBits(); +} + +uint64_t DIExpression::getElement(unsigned Idx) const { + unsigned I = Idx + 1; + assert(I < getNumHeaderFields() && + "non-existing complex address element requested"); + return getHeaderFieldAs<int64_t>(I); } -/// getInlinedAt - If this variable is inlined then return inline location. -MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); } +bool DIExpression::isVariablePiece() const { + return getNumElements() && getElement(0) == dwarf::DW_OP_piece; +} + +uint64_t DIExpression::getPieceOffset() const { + assert(isVariablePiece()); + return getElement(1); +} + +uint64_t DIExpression::getPieceSize() const { + assert(isVariablePiece()); + return getElement(2); +} //===----------------------------------------------------------------------===// // Predicates //===----------------------------------------------------------------------===// -/// isBasicType - Return true if the specified tag is legal for -/// DIBasicType. +bool DIDescriptor::isSubroutineType() const { + return isCompositeType() && getTag() == dwarf::DW_TAG_subroutine_type; +} + bool DIDescriptor::isBasicType() const { if (!DbgNode) return false; @@ -169,7 +197,6 @@ bool DIDescriptor::isBasicType() const { } } -/// isDerivedType - Return true if the specified tag is legal for DIDerivedType. bool DIDescriptor::isDerivedType() const { if (!DbgNode) return false; @@ -192,8 +219,6 @@ bool DIDescriptor::isDerivedType() const { } } -/// isCompositeType - Return true if the specified tag is legal for -/// DICompositeType. bool DIDescriptor::isCompositeType() const { if (!DbgNode) return false; @@ -210,7 +235,6 @@ bool DIDescriptor::isCompositeType() const { } } -/// isVariable - Return true if the specified tag is legal for DIVariable. bool DIDescriptor::isVariable() const { if (!DbgNode) return false; @@ -223,32 +247,19 @@ bool DIDescriptor::isVariable() const { } } -/// isType - Return true if the specified tag is legal for DIType. bool DIDescriptor::isType() const { return isBasicType() || isCompositeType() || isDerivedType(); } -/// isSubprogram - Return true if the specified tag is legal for -/// DISubprogram. bool DIDescriptor::isSubprogram() const { return DbgNode && getTag() == dwarf::DW_TAG_subprogram; } -/// isGlobalVariable - Return true if the specified tag is legal for -/// DIGlobalVariable. bool DIDescriptor::isGlobalVariable() const { return DbgNode && (getTag() == dwarf::DW_TAG_variable || getTag() == dwarf::DW_TAG_constant); } -/// isUnspecifiedParmeter - Return true if the specified tag is -/// DW_TAG_unspecified_parameters. -bool DIDescriptor::isUnspecifiedParameter() const { - return DbgNode && getTag() == dwarf::DW_TAG_unspecified_parameters; -} - -/// isScope - Return true if the specified tag is one of the scope -/// related tag. bool DIDescriptor::isScope() const { if (!DbgNode) return false; @@ -265,83 +276,67 @@ bool DIDescriptor::isScope() const { return isType(); } -/// isTemplateTypeParameter - Return true if the specified tag is -/// DW_TAG_template_type_parameter. bool DIDescriptor::isTemplateTypeParameter() const { return DbgNode && getTag() == dwarf::DW_TAG_template_type_parameter; } -/// 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 || 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. bool DIDescriptor::isCompileUnit() const { return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; } -/// isFile - Return true if the specified tag is DW_TAG_file_type. bool DIDescriptor::isFile() const { return DbgNode && getTag() == dwarf::DW_TAG_file_type; } -/// isNameSpace - Return true if the specified tag is DW_TAG_namespace. bool DIDescriptor::isNameSpace() const { return DbgNode && getTag() == dwarf::DW_TAG_namespace; } -/// isLexicalBlockFile - Return true if the specified descriptor is a -/// lexical block with an extra file. bool DIDescriptor::isLexicalBlockFile() const { return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && - (DbgNode->getNumOperands() == 3); + DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 2; } -/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. bool DIDescriptor::isLexicalBlock() const { + // FIXME: There are always exactly 4 header fields in DILexicalBlock, but + // something relies on this returning true for DILexicalBlockFile. return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && - (DbgNode->getNumOperands() > 3); + DbgNode->getNumOperands() == 3 && + (getNumHeaderFields() == 2 || getNumHeaderFields() == 4); } -/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. bool DIDescriptor::isSubrange() const { return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; } -/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. bool DIDescriptor::isEnumerator() const { return DbgNode && getTag() == dwarf::DW_TAG_enumerator; } -/// isObjCProperty - Return true if the specified tag is DW_TAG_APPLE_property. bool DIDescriptor::isObjCProperty() const { return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; } -/// \brief Return true if the specified tag is DW_TAG_imported_module or -/// DW_TAG_imported_declaration. bool DIDescriptor::isImportedEntity() const { return DbgNode && (getTag() == dwarf::DW_TAG_imported_module || getTag() == dwarf::DW_TAG_imported_declaration); } +bool DIDescriptor::isExpression() const { + return DbgNode && (getTag() == dwarf::DW_TAG_expression); +} + //===----------------------------------------------------------------------===// // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// -unsigned DIArray::getNumElements() const { - if (!DbgNode) - return 0; - return DbgNode->getNumOperands(); -} - -/// replaceAllUsesWith - Replace all uses of the MDNode used by this -/// type with the one in the passed descriptor. -void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { +void DIDescriptor::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { assert(DbgNode && "Trying to replace an unverified type!"); @@ -362,12 +357,10 @@ void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { const Value *V = cast_or_null<Value>(DN); Node->replaceAllUsesWith(const_cast<Value *>(V)); MDNode::deleteTemporary(Node); - DbgNode = D; + DbgNode = DN; } -/// replaceAllUsesWith - Replace all uses of the MDNode used by this -/// type with the one in D. -void DIType::replaceAllUsesWith(MDNode *D) { +void DIDescriptor::replaceAllUsesWith(MDNode *D) { assert(DbgNode && "Trying to replace an unverified type!"); assert(DbgNode != D && "This replacement should always happen"); @@ -378,7 +371,6 @@ void DIType::replaceAllUsesWith(MDNode *D) { MDNode::deleteTemporary(Node); } -/// Verify - Verify that a compile unit is well formed. bool DICompileUnit::Verify() const { if (!isCompileUnit()) return false; @@ -388,19 +380,19 @@ bool DICompileUnit::Verify() const { if (getFilename().empty()) return false; - return DbgNode->getNumOperands() == 14; + return DbgNode->getNumOperands() == 7 && getNumHeaderFields() == 8; } -/// Verify - Verify that an ObjC property is well formed. bool DIObjCProperty::Verify() const { if (!isObjCProperty()) return false; // Don't worry about the rest of the strings for now. - return DbgNode->getNumOperands() == 8; + return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 6; } -/// Check if a field at position Elt of a MDNode is a MDNode. +/// \brief 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) { @@ -412,41 +404,42 @@ static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) { return true; } -/// Check if a field at position Elt of a MDNode is a MDString. +/// \brief Check if a field at position Elt of a MDNode is a MDString. static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) { Value *Fld = getField(DbgNode, Elt); return !Fld || isa<MDString>(Fld); } -/// Check if a value can be a reference to a type. -static bool isTypeRef(const Value *Val) { - return !Val || - (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) || - (isa<MDNode>(Val) && DIType(cast<MDNode>(Val)).isType()); +/// \brief Check if a value can be a reference to a type. +static bool isTypeRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast<MDString>(MD)) + return !S->getString().empty(); + if (auto *N = dyn_cast<MDNode>(MD)) + return DIType(N).isType(); + return false; } -/// Check if a field at position Elt of a MDNode can be a reference to a type. +/// \brief Check if referenced field might be a type. static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return isTypeRef(Fld); + return isTypeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt))); } -/// Check if a value can be a ScopeRef. -static bool isScopeRef(const Value *Val) { - return !Val || - (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) || - // Not checking for Val->isScope() here, because it would work - // only for lexical scopes and not all subclasses of DIScope. - isa<MDNode>(Val); +/// \brief Check if a value can be a ScopeRef. +static bool isScopeRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast<MDString>(MD)) + return !S->getString().empty(); + return isa<MDNode>(MD); } -/// Check if a field at position Elt of a MDNode can be a ScopeRef. +/// \brief Check if a field at position Elt of a MDNode can be a ScopeRef. static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return isScopeRef(Fld); + return isScopeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt))); } -/// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { if (!isType()) return false; @@ -467,6 +460,7 @@ bool DIType::Verify() const { 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()) @@ -479,89 +473,113 @@ bool DIType::Verify() const { return false; } -/// Verify - Verify that a basic type descriptor is well formed. bool DIBasicType::Verify() const { - return isBasicType() && DbgNode->getNumOperands() == 10; + return isBasicType() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 8; } -/// Verify - Verify that a derived type descriptor is well formed. bool DIDerivedType::Verify() const { - // Make sure DerivedFrom @ field 9 is TypeRef. - if (!fieldIsTypeRef(DbgNode, 9)) + // Make sure DerivedFrom @ field 3 is TypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; if (getTag() == dwarf::DW_TAG_ptr_to_member_type) - // Make sure ClassType @ field 10 is a TypeRef. - if (!fieldIsTypeRef(DbgNode, 10)) + // Make sure ClassType @ field 4 is a TypeRef. + if (!fieldIsTypeRef(DbgNode, 4)) return false; - return isDerivedType() && DbgNode->getNumOperands() >= 10 && - DbgNode->getNumOperands() <= 14; + return isDerivedType() && DbgNode->getNumOperands() >= 4 && + DbgNode->getNumOperands() <= 8 && getNumHeaderFields() >= 7 && + getNumHeaderFields() <= 8; } -/// Verify - Verify that a composite type descriptor is well formed. bool DICompositeType::Verify() const { if (!isCompositeType()) return false; - // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are TypeRef. - if (!fieldIsTypeRef(DbgNode, 9)) + // Make sure DerivedFrom @ field 3 and ContainingType @ field 5 are TypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; - if (!fieldIsTypeRef(DbgNode, 12)) + if (!fieldIsTypeRef(DbgNode, 5)) return false; - // Make sure the type identifier at field 14 is MDString, it can be null. - if (!fieldIsMDString(DbgNode, 14)) + // Make sure the type identifier at field 7 is MDString, it can be null. + if (!fieldIsMDString(DbgNode, 7)) return false; // A subroutine type can't be both & and &&. if (isLValueReference() && isRValueReference()) return false; - return DbgNode->getNumOperands() == 15; + return DbgNode->getNumOperands() == 8 && getNumHeaderFields() == 8; } -/// Verify - Verify that a subprogram descriptor is well formed. bool DISubprogram::Verify() const { if (!isSubprogram()) return false; - // Make sure context @ field 2 is a ScopeRef and type @ field 7 is a MDNode. + // Make sure context @ field 2 is a ScopeRef and type @ field 3 is a MDNode. if (!fieldIsScopeRef(DbgNode, 2)) return false; - if (!fieldIsMDNode(DbgNode, 7)) + if (!fieldIsMDNode(DbgNode, 3)) return false; - // Containing type @ field 12. - if (!fieldIsTypeRef(DbgNode, 12)) + // Containing type @ field 4. + if (!fieldIsTypeRef(DbgNode, 4)) return false; // A subprogram can't be both & and &&. if (isLValueReference() && isRValueReference()) return false; - return DbgNode->getNumOperands() == 20; + // If a DISubprogram has an llvm::Function*, then scope chains from all + // instructions within the function should lead to this DISubprogram. + if (auto *F = getFunction()) { + LLVMContext &Ctxt = F->getContext(); + for (auto &BB : *F) { + for (auto &I : BB) { + DebugLoc DL = I.getDebugLoc(); + if (DL.isUnknown()) + continue; + + MDNode *Scope = nullptr; + MDNode *IA = nullptr; + // walk the inlined-at scopes + while (DL.getScopeAndInlinedAt(Scope, IA, F->getContext()), IA) + DL = DebugLoc::getFromDILocation(IA); + DL.getScopeAndInlinedAt(Scope, IA, Ctxt); + assert(!IA); + while (!DIDescriptor(Scope).isSubprogram()) { + DILexicalBlockFile D(Scope); + Scope = D.isLexicalBlockFile() + ? D.getScope() + : DebugLoc::getFromDILexicalBlock(Scope).getScope(Ctxt); + } + if (!DISubprogram(Scope).describes(F)) + return false; + } + } + } + return DbgNode->getNumOperands() == 9 && getNumHeaderFields() == 12; } -/// Verify - Verify that a global variable descriptor is well formed. bool DIGlobalVariable::Verify() const { if (!isGlobalVariable()) return false; if (getDisplayName().empty()) return false; - // Make sure context @ field 2 is an MDNode. - if (!fieldIsMDNode(DbgNode, 2)) + // Make sure context @ field 1 is a ScopeRef. + if (!fieldIsScopeRef(DbgNode, 1)) return false; - // Make sure that type @ field 8 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 8)) + // Make sure that type @ field 3 is a DITypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; - // Make sure StaticDataMemberDeclaration @ field 12 is MDNode. - if (!fieldIsMDNode(DbgNode, 12)) + // Make sure StaticDataMemberDeclaration @ field 5 is MDNode. + if (!fieldIsMDNode(DbgNode, 5)) return false; - return DbgNode->getNumOperands() == 13; + return DbgNode->getNumOperands() == 6 && getNumHeaderFields() == 7; } -/// Verify - Verify that a variable descriptor is well formed. bool DIVariable::Verify() const { if (!isVariable()) return false; @@ -569,19 +587,31 @@ bool DIVariable::Verify() const { // Make sure context @ field 1 is an MDNode. if (!fieldIsMDNode(DbgNode, 1)) return false; - // Make sure that type @ field 5 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 5)) + // Make sure that type @ field 3 is a DITypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; - // Variable without a complex expression. - if (DbgNode->getNumOperands() == 8) + // Check the number of header fields, which is common between complex and + // simple variables. + if (getNumHeaderFields() != 4) + return false; + + // Variable without an inline location. + if (DbgNode->getNumOperands() == 4) + return true; + + // Variable with an inline location. + return getInlinedAt() != nullptr && DbgNode->getNumOperands() == 5; +} + +bool DIExpression::Verify() const { + // Empty DIExpressions may be represented as a nullptr. + if (!DbgNode) return true; - // Make sure the complex expression is an MDNode. - return (DbgNode->getNumOperands() == 9 && fieldIsMDNode(DbgNode, 8)); + return isExpression() && DbgNode->getNumOperands() == 1; } -/// Verify - Verify that a location descriptor is well formed. bool DILocation::Verify() const { if (!DbgNode) return false; @@ -589,69 +619,59 @@ bool DILocation::Verify() const { return DbgNode->getNumOperands() == 4; } -/// Verify - Verify that a namespace descriptor is well formed. bool DINameSpace::Verify() const { if (!isNameSpace()) return false; - return DbgNode->getNumOperands() == 5; + return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 3; } -/// \brief Retrieve the MDNode for the directory/file pair. MDNode *DIFile::getFileNode() const { return getNodeField(DbgNode, 1); } -/// \brief Verify that the file descriptor is well formed. bool DIFile::Verify() const { return isFile() && DbgNode->getNumOperands() == 2; } -/// \brief Verify that the enumerator descriptor is well formed. bool DIEnumerator::Verify() const { - return isEnumerator() && DbgNode->getNumOperands() == 3; + return isEnumerator() && DbgNode->getNumOperands() == 1 && + getNumHeaderFields() == 3; } -/// \brief Verify that the subrange descriptor is well formed. bool DISubrange::Verify() const { - return isSubrange() && DbgNode->getNumOperands() == 3; + return isSubrange() && DbgNode->getNumOperands() == 1 && + getNumHeaderFields() == 3; } -/// \brief Verify that the lexical block descriptor is well formed. bool DILexicalBlock::Verify() const { - return isLexicalBlock() && DbgNode->getNumOperands() == 7; + return isLexicalBlock() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 4; } -/// \brief Verify that the file-scoped lexical block descriptor is well formed. bool DILexicalBlockFile::Verify() const { - return isLexicalBlockFile() && DbgNode->getNumOperands() == 3; -} - -/// \brief Verify that an unspecified parameter descriptor is well formed. -bool DIUnspecifiedParameter::Verify() const { - return isUnspecifiedParameter() && DbgNode->getNumOperands() == 1; + return isLexicalBlockFile() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 2; } -/// \brief Verify that the template type parameter descriptor is well formed. bool DITemplateTypeParameter::Verify() const { - return isTemplateTypeParameter() && DbgNode->getNumOperands() == 7; + return isTemplateTypeParameter() && DbgNode->getNumOperands() == 4 && + getNumHeaderFields() == 4; } -/// \brief Verify that the template value parameter descriptor is well formed. bool DITemplateValueParameter::Verify() const { - return isTemplateValueParameter() && DbgNode->getNumOperands() == 8; + return isTemplateValueParameter() && DbgNode->getNumOperands() == 5 && + getNumHeaderFields() == 4; } -/// \brief Verify that the imported module descriptor is well formed. bool DIImportedEntity::Verify() const { - return isImportedEntity() && - (DbgNode->getNumOperands() == 4 || DbgNode->getNumOperands() == 5); + return isImportedEntity() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 3; } -/// getObjCProperty - Return property node, if this ivar is associated with one. MDNode *DIDerivedType::getObjCProperty() const { - return getNodeField(DbgNode, 10); + return getNodeField(DbgNode, 4); } MDString *DICompositeType::getIdentifier() const { - return cast_or_null<MDString>(getField(DbgNode, 14)); + return cast_or_null<MDString>(getField(DbgNode, 7)); } #ifndef NDEBUG @@ -669,27 +689,21 @@ static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) { } #endif -/// \brief Set the array of member DITypes. -void DICompositeType::setTypeArray(DIArray Elements, DIArray TParams) { - assert((!TParams || DbgNode->getNumOperands() == 15) && - "If you're setting the template parameters this should include a slot " - "for that!"); +void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) { TrackingVH<MDNode> N(*this); if (Elements) { #ifndef NDEBUG // Check that the new list of members contains all the old members as well. - if (const MDNode *El = cast_or_null<MDNode>(N->getOperand(10))) + if (const MDNode *El = cast_or_null<MDNode>(N->getOperand(4))) VerifySubsetOf(El, Elements); #endif - N->replaceOperandWith(10, Elements); + N->replaceOperandWith(4, Elements); } if (TParams) - N->replaceOperandWith(13, TParams); + N->replaceOperandWith(6, TParams); DbgNode = N; } -/// Generate a reference to this DIType. Uses the type identifier instead -/// of the actual MDNode if possible, to help type uniquing. DIScopeRef DIScope::getRef() const { if (!isCompositeType()) return DIScopeRef(*this); @@ -699,15 +713,12 @@ DIScopeRef DIScope::getRef() const { return DIScopeRef(DTy.getIdentifier()); } -/// \brief Set the containing type. void DICompositeType::setContainingType(DICompositeType ContainingType) { TrackingVH<MDNode> N(*this); - N->replaceOperandWith(12, ContainingType.getRef()); + N->replaceOperandWith(5, ContainingType.getRef()); DbgNode = N; } -/// isInlinedFnArgument - Return true if this variable provides debugging -/// information for an inlined function arguments. bool DIVariable::isInlinedFnArgument(const Function *CurFn) { assert(CurFn && "Invalid function"); if (!getContext().isSubprogram()) @@ -717,8 +728,6 @@ bool DIVariable::isInlinedFnArgument(const Function *CurFn) { return !DISubprogram(getContext()).describes(CurFn); } -/// describes - Return true if this subprogram provides debugging -/// information for the function F. bool DISubprogram::describes(const Function *F) { assert(F && "Invalid function"); if (F == getFunction()) @@ -731,27 +740,18 @@ bool DISubprogram::describes(const Function *F) { return false; } -unsigned DISubprogram::isOptimized() const { - assert(DbgNode && "Invalid subprogram descriptor!"); - if (DbgNode->getNumOperands() == 15) - return getUnsignedField(14); - return 0; -} - MDNode *DISubprogram::getVariablesNodes() const { - return getNodeField(DbgNode, 18); + return getNodeField(DbgNode, 8); } DIArray DISubprogram::getVariables() const { - return DIArray(getNodeField(DbgNode, 18)); + return DIArray(getNodeField(DbgNode, 8)); } Value *DITemplateValueParameter::getValue() const { - return getField(DbgNode, 4); + return getField(DbgNode, 3); } -// If the current node has a parent scope then return that, -// else return an empty scope. DIScopeRef DIScope::getContext() const { if (isType()) @@ -773,7 +773,6 @@ DIScopeRef DIScope::getContext() const { return DIScopeRef(nullptr); } -// If the scope node has a name, return that, else return an empty string. StringRef DIScope::getName() const { if (isType()) return DIType(DbgNode).getName(); @@ -800,44 +799,58 @@ StringRef DIScope::getDirectory() const { } DIArray DICompileUnit::getEnumTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 7)); + return DIArray(getNodeField(DbgNode, 2)); } DIArray DICompileUnit::getRetainedTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 8)); + return DIArray(getNodeField(DbgNode, 3)); } DIArray DICompileUnit::getSubprograms() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 9)); + return DIArray(getNodeField(DbgNode, 4)); } DIArray DICompileUnit::getGlobalVariables() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 10)); + return DIArray(getNodeField(DbgNode, 5)); } DIArray DICompileUnit::getImportedEntities() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 11)); + return DIArray(getNodeField(DbgNode, 6)); +} + +void DICompileUnit::replaceSubprograms(DIArray Subprograms) { + assert(Verify() && "Expected compile unit"); + if (Subprograms == getSubprograms()) + return; + + const_cast<MDNode *>(DbgNode)->replaceOperandWith(4, Subprograms); +} + +void DICompileUnit::replaceGlobalVariables(DIArray GlobalVariables) { + assert(Verify() && "Expected compile unit"); + if (GlobalVariables == getGlobalVariables()) + return; + + const_cast<MDNode *>(DbgNode)->replaceOperandWith(5, GlobalVariables); } -/// copyWithNewScope - Return a copy of this location, replacing the -/// current scope with the given one. DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, - DILexicalBlock NewScope) { + DILexicalBlockFile NewScope) { SmallVector<Value *, 10> Elts; assert(Verify()); for (unsigned I = 0; I < DbgNode->getNumOperands(); ++I) { @@ -850,78 +863,43 @@ DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, return DILocation(NewDIL); } -/// computeNewDiscriminator - Generate a new discriminator value for this -/// file and line location. unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) { std::pair<const char *, unsigned> Key(getFilename().data(), getLineNumber()); return ++Ctx.pImpl->DiscriminatorTable[Key]; } -/// fixupSubprogramName - Replace contains special characters used -/// in a typical Objective-C names with '.' in a given string. -static void fixupSubprogramName(DISubprogram Fn, SmallVectorImpl<char> &Out) { - StringRef FName = - Fn.getFunction() ? Fn.getFunction()->getName() : Fn.getName(); - FName = Function::getRealLinkageName(FName); - - StringRef Prefix("llvm.dbg.lv."); - Out.reserve(FName.size() + Prefix.size()); - Out.append(Prefix.begin(), Prefix.end()); - - bool isObjCLike = false; - for (size_t i = 0, e = FName.size(); i < e; ++i) { - char C = FName[i]; - if (C == '[') - isObjCLike = true; +DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext) { + assert(DIVariable(DV).Verify() && "Expected a DIVariable"); + if (!InlinedScope) + return cleanseInlinedVariable(DV, VMContext); - if (isObjCLike && (C == '[' || C == ']' || C == ' ' || C == ':' || - C == '+' || C == '(' || C == ')')) - Out.push_back('.'); - else - Out.push_back(C); - } -} + // Insert inlined scope. + SmallVector<Value *, 8> Elts; + for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) + Elts.push_back(DV->getOperand(I)); + Elts.push_back(InlinedScope); -/// getFnSpecificMDNode - Return a NameMDNode, if available, that is -/// suitable to hold function specific information. -NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, DISubprogram Fn) { - SmallString<32> Name; - fixupSubprogramName(Fn, Name); - return M.getNamedMetadata(Name.str()); + DIVariable Inlined(MDNode::get(VMContext, Elts)); + assert(Inlined.Verify() && "Expected to create a DIVariable"); + return Inlined; } -/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable -/// to hold function specific information. -NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) { - SmallString<32> Name; - fixupSubprogramName(Fn, Name); - return M.getOrInsertNamedMetadata(Name.str()); -} +DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { + assert(DIVariable(DV).Verify() && "Expected a DIVariable"); + if (!DIVariable(DV).getInlinedAt()) + return DIVariable(DV); -/// createInlinedVariable - Create a new inlined variable based on current -/// variable. -/// @param DV Current Variable. -/// @param InlinedScope Location at current variable is inlined. -DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext) { - SmallVector<Value *, 16> Elts; - // Insert inlined scope as 7th element. - for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) - i == 7 ? Elts.push_back(InlinedScope) : Elts.push_back(DV->getOperand(i)); - return DIVariable(MDNode::get(VMContext, Elts)); -} + // Remove inlined scope. + SmallVector<Value *, 8> Elts; + for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) + Elts.push_back(DV->getOperand(I)); -/// cleanseInlinedVariable - Remove inlined scope from the variable. -DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { - SmallVector<Value *, 16> Elts; - // Insert inlined scope as 7th element. - for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) - i == 7 ? Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))) - : Elts.push_back(DV->getOperand(i)); - return DIVariable(MDNode::get(VMContext, Elts)); + DIVariable Cleansed(MDNode::get(VMContext, Elts)); + assert(Cleansed.Verify() && "Expected to create a DIVariable"); + return Cleansed; } -/// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram llvm::getDISubprogram(const MDNode *Scope) { DIDescriptor D(Scope); if (D.isSubprogram()) @@ -936,7 +914,23 @@ DISubprogram llvm::getDISubprogram(const MDNode *Scope) { return DISubprogram(); } -/// getDICompositeType - Find underlying composite type. +DISubprogram llvm::getDISubprogram(const Function *F) { + // We look for the first instr that has a debug annotation leading back to F. + for (auto &BB : *F) { + auto Inst = std::find_if(BB.begin(), BB.end(), [](const Instruction &Inst) { + return !Inst.getDebugLoc().isUnknown(); + }); + if (Inst == BB.end()) + continue; + DebugLoc DLoc = Inst->getDebugLoc(); + const MDNode *Scope = DLoc.getScopeNode(F->getParent()->getContext()); + DISubprogram Subprogram = getDISubprogram(Scope); + return Subprogram.describes(F) ? Subprogram : DISubprogram(); + } + + return DISubprogram(); +} + DICompositeType llvm::getDICompositeType(DIType T) { if (T.isCompositeType()) return DICompositeType(T); @@ -953,7 +947,6 @@ DICompositeType llvm::getDICompositeType(DIType T) { return DICompositeType(); } -/// Update DITypeIdentifierMap by going through retained types of each CU. DITypeIdentifierMap llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) { DITypeIdentifierMap Map; @@ -1002,7 +995,6 @@ void DebugInfoFinder::InitializeTypeMap(const Module &M) { } } -/// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(const Module &M) { InitializeTypeMap(M); if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { @@ -1013,7 +1005,7 @@ void DebugInfoFinder::processModule(const Module &M) { for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { DIGlobalVariable DIG(GVs.getElement(i)); if (addGlobalVariable(DIG)) { - processScope(DIG.getContext()); + processScope(DIG.getContext().resolve(TypeIdentifierMap)); processType(DIG.getType().resolve(TypeIdentifierMap)); } } @@ -1041,7 +1033,6 @@ void DebugInfoFinder::processModule(const Module &M) { } } -/// processLocation - Process DILocation. void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { if (!Loc) return; @@ -1050,7 +1041,6 @@ void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { processLocation(M, Loc.getOrigLocation()); } -/// processType - Process DIType. void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; @@ -1058,7 +1048,13 @@ void DebugInfoFinder::processType(DIType DT) { if (DT.isCompositeType()) { DICompositeType DCT(DT); processType(DCT.getTypeDerivedFrom().resolve(TypeIdentifierMap)); - DIArray DA = DCT.getTypeArray(); + if (DT.isSubroutineType()) { + DITypeArray DTA = DISubroutineType(DT).getTypeArray(); + for (unsigned i = 0, e = DTA.getNumElements(); i != e; ++i) + processType(DTA.getElement(i).resolve(TypeIdentifierMap)); + return; + } + DIArray DA = DCT.getElements(); for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { DIDescriptor D = DA.getElement(i); if (D.isType()) @@ -1100,7 +1096,6 @@ void DebugInfoFinder::processScope(DIScope Scope) { } } -/// processSubprogram - Process DISubprogram. void DebugInfoFinder::processSubprogram(DISubprogram SP) { if (!addSubprogram(SP)) return; @@ -1121,7 +1116,6 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) { } } -/// processDeclare - Process DbgDeclareInst. void DebugInfoFinder::processDeclare(const Module &M, const DbgDeclareInst *DDI) { MDNode *N = dyn_cast<MDNode>(DDI->getVariable()); @@ -1133,7 +1127,7 @@ void DebugInfoFinder::processDeclare(const Module &M, if (!DV.isVariable()) return; - if (!NodesSeen.insert(DV)) + if (!NodesSeen.insert(DV).second) return; processScope(DIVariable(N).getContext()); processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); @@ -1149,53 +1143,49 @@ void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) { if (!DV.isVariable()) return; - if (!NodesSeen.insert(DV)) + if (!NodesSeen.insert(DV).second) return; processScope(DIVariable(N).getContext()); processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); } -/// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { if (!DT) return false; - if (!NodesSeen.insert(DT)) + if (!NodesSeen.insert(DT).second) return false; TYs.push_back(DT); return true; } -/// addCompileUnit - Add compile unit into CUs. bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { if (!CU) return false; - if (!NodesSeen.insert(CU)) + if (!NodesSeen.insert(CU).second) return false; CUs.push_back(CU); return true; } -/// addGlobalVariable - Add global variable into GVs. bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { if (!DIG) return false; - if (!NodesSeen.insert(DIG)) + if (!NodesSeen.insert(DIG).second) return false; GVs.push_back(DIG); return true; } -// addSubprogram - Add subprgoram into SPs. bool DebugInfoFinder::addSubprogram(DISubprogram SP) { if (!SP) return false; - if (!NodesSeen.insert(SP)) + if (!NodesSeen.insert(SP).second) return false; SPs.push_back(SP); @@ -1209,7 +1199,7 @@ bool DebugInfoFinder::addScope(DIScope Scope) { // as null for now. if (Scope->getNumOperands() == 0) return false; - if (!NodesSeen.insert(Scope)) + if (!NodesSeen.insert(Scope).second) return false; Scopes.push_back(Scope); return true; @@ -1219,13 +1209,11 @@ bool DebugInfoFinder::addScope(DIScope Scope) { // DIDescriptor: dump routines for all descriptors. //===----------------------------------------------------------------------===// -/// dump - Print descriptor to dbgs() with a newline. void DIDescriptor::dump() const { print(dbgs()); dbgs() << '\n'; } -/// print - Print descriptor. void DIDescriptor::print(raw_ostream &OS) const { if (!DbgNode) return; @@ -1259,6 +1247,8 @@ void DIDescriptor::print(raw_ostream &OS) const { DINameSpace(DbgNode).printInternal(OS); } else if (this->isScope()) { DIScope(DbgNode).printInternal(OS); + } else if (this->isExpression()) { + DIExpression(DbgNode).printInternal(OS); } } @@ -1311,6 +1301,8 @@ void DIType::printInternal(raw_ostream &OS) const { OS << " [private]"; else if (isProtected()) OS << " [protected]"; + else if (isPublic()) + OS << " [public]"; if (isArtificial()) OS << " [artificial]"; @@ -1341,7 +1333,7 @@ void DIDerivedType::printInternal(raw_ostream &OS) const { void DICompositeType::printInternal(raw_ostream &OS) const { DIType::printInternal(OS); - DIArray A = getTypeArray(); + DIArray A = getElements(); OS << " [" << A.getNumElements() << " elements]"; } @@ -1370,6 +1362,8 @@ void DISubprogram::printInternal(raw_ostream &OS) const { OS << " [private]"; else if (isProtected()) OS << " [protected]"; + else if (isPublic()) + OS << " [public]"; if (isLValueReference()) OS << " [reference]"; @@ -1406,6 +1400,30 @@ void DIVariable::printInternal(raw_ostream &OS) const { OS << " [line " << getLineNumber() << ']'; } +void DIExpression::printInternal(raw_ostream &OS) const { + for (unsigned I = 0; I < getNumElements(); ++I) { + uint64_t OpCode = getElement(I); + OS << " [" << OperationEncodingString(OpCode); + switch (OpCode) { + case DW_OP_plus: { + OS << " " << getElement(++I); + break; + } + case DW_OP_piece: { + unsigned Offset = getElement(++I); + unsigned Size = getElement(++I); + OS << " offset=" << Offset << ", size=" << Size; + break; + } + default: + // Else bail out early. This may be a line table entry. + OS << "Unknown]"; + return; + } + OS << "]"; + } +} + void DIObjCProperty::printInternal(raw_ostream &OS) const { StringRef Name = getObjCPropertyName(); if (!Name.empty()) @@ -1449,30 +1467,22 @@ void DIVariable::printExtendedName(raw_ostream &OS) const { } } -/// Specialize constructor to make sure it has the correct type. -template <> DIRef<DIScope>::DIRef(const Value *V) : Val(V) { +template <> DIRef<DIScope>::DIRef(const Metadata *V) : Val(V) { assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode"); } -template <> DIRef<DIType>::DIRef(const Value *V) : Val(V) { +template <> DIRef<DIType>::DIRef(const Metadata *V) : Val(V) { assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode"); } -/// Specialize getFieldAs to handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const { - return DIScopeRef(getField(DbgNode, Elt)); + return DIScopeRef(cast_or_null<Metadata>(getField(DbgNode, Elt))); } -/// Specialize getFieldAs to handle fields that are references to DITypes. template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const { - return DITypeRef(getField(DbgNode, Elt)); + return DITypeRef(cast_or_null<Metadata>(getField(DbgNode, Elt))); } -/// Strip debug info in the module if it exists. -/// To do this, we remove all calls to the debugger intrinsics and any named -/// metadata for debugging. We also remove debug locations for instructions. -/// Return true if module is modified. bool llvm::StripDebugInfo(Module &M) { - bool Changed = false; // Remove all of the calls to the debugger intrinsics, and remove them from @@ -1519,7 +1529,6 @@ bool llvm::StripDebugInfo(Module &M) { return Changed; } -/// Return Debug Info Metadata Version by checking module flags. unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { Value *Val = M.getModuleFlag("Debug Info Version"); if (!Val) diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp index e8bdccebae..718da852fe 100644 --- a/lib/IR/DebugLoc.cpp +++ b/lib/IR/DebugLoc.cpp @@ -79,14 +79,8 @@ MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const { DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) const { const MDNode *Scope = getScopeNode(Ctx); DISubprogram SP = getDISubprogram(Scope); - if (SP.isSubprogram()) { - // Check for number of operands since the compatibility is - // cheap here. FIXME: Name the magic constant. - if (SP->getNumOperands() > 19) - return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); - else - return DebugLoc::get(SP.getLineNumber(), 0, SP); - } + if (SP.isSubprogram()) + return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); return DebugLoc(); } diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index 2727063600..37cce2b0d7 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -127,20 +127,20 @@ void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { DP << getMsg(); } -bool DiagnosticInfoOptimizationRemarkBase::isLocationAvailable() const { +bool DiagnosticInfoOptimizationBase::isLocationAvailable() const { return getDebugLoc().isUnknown() == false; } -void DiagnosticInfoOptimizationRemarkBase::getLocation(StringRef *Filename, - unsigned *Line, - unsigned *Column) const { +void DiagnosticInfoOptimizationBase::getLocation(StringRef *Filename, + unsigned *Line, + unsigned *Column) const { DILocation DIL(getDebugLoc().getAsMDNode(getFunction().getContext())); *Filename = DIL.getFilename(); *Line = DIL.getLineNumber(); *Column = DIL.getColumnNumber(); } -const std::string DiagnosticInfoOptimizationRemarkBase::getLocationStr() const { +const std::string DiagnosticInfoOptimizationBase::getLocationStr() const { StringRef Filename("<unknown>"); unsigned Line = 0; unsigned Column = 0; @@ -149,7 +149,7 @@ const std::string DiagnosticInfoOptimizationRemarkBase::getLocationStr() const { return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); } -void DiagnosticInfoOptimizationRemarkBase::print(DiagnosticPrinter &DP) const { +void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { DP << getLocationStr() << ": " << getMsg(); } @@ -189,3 +189,20 @@ void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx, Ctx.diagnose( DiagnosticInfoOptimizationRemarkAnalysis(PassName, Fn, DLoc, Msg)); } + +bool DiagnosticInfoOptimizationFailure::isEnabled() const { + // Only print warnings. + return getSeverity() == DS_Warning; +} + +void llvm::emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) { + Ctx.diagnose(DiagnosticInfoOptimizationFailure( + Fn, DLoc, Twine("loop not vectorized: " + Msg))); +} + +void llvm::emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) { + Ctx.diagnose(DiagnosticInfoOptimizationFailure( + Fn, DLoc, Twine("loop not interleaved: " + Msg))); +} diff --git a/lib/IR/DiagnosticPrinter.cpp b/lib/IR/DiagnosticPrinter.cpp index 5e160266c8..f25fc20a19 100644 --- a/lib/IR/DiagnosticPrinter.cpp +++ b/lib/IR/DiagnosticPrinter.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the a diagnostic printer relying on raw_ostream. +// This file defines a diagnostic printer relying on raw_ostream. // //===----------------------------------------------------------------------===// diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 14435711bb..32b2ec5845 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -77,11 +77,17 @@ unsigned Argument::getArgNo() const { } /// hasNonNullAttr - Return true if this argument has the nonnull attribute on -/// it in its containing function. +/// it in its containing function. Also returns true if at least one byte is +/// known to be dereferenceable and the pointer is in addrspace(0). bool Argument::hasNonNullAttr() const { if (!getType()->isPointerTy()) return false; - return getParent()->getAttributes(). - hasAttribute(getArgNo()+1, Attribute::NonNull); + if (getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::NonNull)) + return true; + else if (getDereferenceableBytes() > 0 && + getType()->getPointerAddressSpace() == 0) + return true; + return false; } /// hasByValAttr - Return true if this argument has the byval attribute on it @@ -113,6 +119,12 @@ unsigned Argument::getParamAlignment() const { } +uint64_t Argument::getDereferenceableBytes() const { + assert(getType()->isPointerTy() && + "Only pointers have dereferenceable bytes"); + return getParent()->getDereferenceableBytes(getArgNo()+1); +} + /// hasNestAttr - Return true if this argument has the nest attribute on /// it in its containing function. bool Argument::hasNestAttr() const { @@ -154,6 +166,20 @@ bool Argument::hasReturnedAttr() const { hasAttribute(getArgNo()+1, Attribute::Returned); } +/// hasZExtAttr - Return true if this argument has the zext attribute on it in +/// its containing function. +bool Argument::hasZExtAttr() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::ZExt); +} + +/// hasSExtAttr Return true if this argument has the sext attribute on it in its +/// containing function. +bool Argument::hasSExtAttr() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::SExt); +} + /// Return true if this argument has the readonly or readnone attribute on it /// in its containing function. bool Argument::onlyReadsMemory() const { @@ -187,6 +213,12 @@ void Argument::removeAttr(AttributeSet AS) { // Helper Methods in Function //===----------------------------------------------------------------------===// +bool Function::isMaterializable() const { + return getGlobalObjectSubClassData(); +} + +void Function::setIsMaterializable(bool V) { setGlobalObjectSubClassData(V); } + LLVMContext &Function::getContext() const { return getType()->getContext(); } @@ -215,12 +247,13 @@ void Function::eraseFromParent() { // Function Implementation //===----------------------------------------------------------------------===// -Function::Function(FunctionType *Ty, LinkageTypes Linkage, - const Twine &name, Module *ParentModule) - : GlobalObject(PointerType::getUnqual(Ty), - Value::FunctionVal, nullptr, 0, Linkage, name) { +Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name, + Module *ParentModule) + : GlobalObject(PointerType::getUnqual(Ty), Value::FunctionVal, nullptr, 0, + Linkage, name) { assert(FunctionType::isValidReturnType(getReturnType()) && "invalid return type"); + setIsMaterializable(false); SymTab = new ValueSymbolTable(); // If the function has arguments, mark them as lazily built. @@ -292,6 +325,8 @@ void Function::setParent(Module *parent) { // delete. // void Function::dropAllReferences() { + setIsMaterializable(false); + for (iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); @@ -420,6 +455,33 @@ unsigned Function::lookupIntrinsicID() const { return 0; } +/// Returns a stable mangling for the type specified for use in the name +/// mangling scheme used by 'any' types in intrinsic signatures. +static std::string getMangledTypeStr(Type* Ty) { + std::string Result; + if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) { + Result += "p" + llvm::utostr(PTyp->getAddressSpace()) + + getMangledTypeStr(PTyp->getElementType()); + } else if (ArrayType* ATyp = dyn_cast<ArrayType>(Ty)) { + Result += "a" + llvm::utostr(ATyp->getNumElements()) + + getMangledTypeStr(ATyp->getElementType()); + } else if (StructType* STyp = dyn_cast<StructType>(Ty)) { + if (!STyp->isLiteral()) + Result += STyp->getName(); + else + llvm_unreachable("TODO: implement literal types"); + } else if (FunctionType* FT = dyn_cast<FunctionType>(Ty)) { + Result += "f_" + getMangledTypeStr(FT->getReturnType()); + for (size_t i = 0; i < FT->getNumParams(); i++) + Result += getMangledTypeStr(FT->getParamType(i)); + if (FT->isVarArg()) + Result += "vararg"; + Result += "f"; //ensure distinguishable + } else if (Ty) + Result += EVT::getEVT(Ty).getEVTString(); + return Result; +} + std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) { assert(id < num_intrinsics && "Invalid intrinsic ID!"); static const char * const Table[] = { @@ -432,12 +494,7 @@ std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) { return Table[id]; std::string Result(Table[id]); for (unsigned i = 0; i < Tys.size(); ++i) { - if (PointerType* PTyp = dyn_cast<PointerType>(Tys[i])) { - Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) + - EVT::getEVT(PTyp->getElementType()).getEVTString(); - } - else if (Tys[i]) - Result += "." + EVT::getEVT(Tys[i]).getEVTString(); + Result += "." + getMangledTypeStr(Tys[i]); } return Result; } @@ -467,19 +524,20 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_METADATA = 18, + IIT_EMPTYSTRUCT = 19, + IIT_STRUCT2 = 20, + IIT_STRUCT3 = 21, + IIT_STRUCT4 = 22, + IIT_STRUCT5 = 23, + IIT_EXTEND_ARG = 24, + IIT_TRUNC_ARG = 25, + IIT_ANYPTR = 26, + IIT_V1 = 27, + IIT_VARARG = 28, + IIT_HALF_VEC_ARG = 29 }; @@ -550,6 +608,10 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 32)); DecodeIITType(NextElt, Infos, OutputTable); return; + case IIT_V64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 64)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_PTR: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0)); DecodeIITType(NextElt, Infos, OutputTable); @@ -666,7 +728,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos, assert(D.Struct_NumElements <= 5 && "Can't handle this yet"); for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) Elts[i] = DecodeFixedType(Infos, Tys, Context); - return StructType::get(Context, ArrayRef<Type*>(Elts,D.Struct_NumElements)); + return StructType::get(Context, makeArrayRef(Elts,D.Struct_NumElements)); } case IITDescriptor::Argument: @@ -708,6 +770,12 @@ FunctionType *Intrinsic::getType(LLVMContext &Context, while (!TableRef.empty()) ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context)); + // DecodeFixedType returns Void for IITDescriptor::Void and IITDescriptor::VarArg + // If we see void type as the type of the last argument, it is vararg intrinsic + if (!ArgTys.empty() && ArgTys.back()->isVoidTy()) { + ArgTys.pop_back(); + return FunctionType::get(ResultTy, ArgTys, true); + } return FunctionType::get(ResultTy, ArgTys, false); } diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp index 1667401f88..245c500cf6 100644 --- a/lib/IR/GCOV.cpp +++ b/lib/IR/GCOV.cpp @@ -298,7 +298,8 @@ uint64_t GCOVFunction::getExitCount() const { /// dump - Dump GCOVFunction content to dbgs() for debugging purposes. void GCOVFunction::dump() const { - dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n"; + dbgs() << "===== " << Name << " (" << Ident << ") @ " << Filename << ":" + << LineNumber << "\n"; for (const auto &Block : Blocks) Block->dump(); } @@ -517,11 +518,11 @@ FileInfo::openCoveragePath(StringRef CoveragePath) { if (Options.NoOutput) return llvm::make_unique<raw_null_ostream>(); - std::string ErrorInfo; - auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath.str().c_str(), - ErrorInfo, sys::fs::F_Text); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << "\n"; + std::error_code EC; + auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath.str(), EC, + sys::fs::F_Text); + if (EC) { + errs() << EC.message() << "\n"; return llvm::make_unique<raw_null_ostream>(); } return std::move(OS); diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 244e3e4bae..e181d623b8 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -29,13 +29,15 @@ using namespace llvm; //===----------------------------------------------------------------------===// bool GlobalValue::isMaterializable() const { - return getParent() && getParent()->isMaterializable(this); + if (const Function *F = dyn_cast<Function>(this)) + return F->isMaterializable(); + return false; } bool GlobalValue::isDematerializable() const { return getParent() && getParent()->isDematerializable(this); } -bool GlobalValue::Materialize(std::string *ErrInfo) { - return getParent()->Materialize(this, ErrInfo); +std::error_code GlobalValue::materialize() { + return getParent()->materialize(this); } void GlobalValue::Dematerialize() { getParent()->Dematerialize(this); @@ -77,10 +79,24 @@ void GlobalObject::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); assert(Align <= MaximumAlignment && "Alignment is greater than MaximumAlignment!"); - setGlobalValueSubClassData(Log2_32(Align) + 1); + unsigned AlignmentData = Log2_32(Align) + 1; + unsigned OldData = getGlobalValueSubClassData(); + setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData); assert(getAlignment() == Align && "Alignment representation error!"); } +unsigned GlobalObject::getGlobalObjectSubClassData() const { + unsigned ValueData = getGlobalValueSubClassData(); + return ValueData >> AlignmentBits; +} + +void GlobalObject::setGlobalObjectSubClassData(unsigned Val) { + unsigned OldData = getGlobalValueSubClassData(); + setGlobalValueSubClassData((OldData & AlignmentMask) | + (Val << AlignmentBits)); + assert(getGlobalObjectSubClassData() == Val && "representation error"); +} + void GlobalObject::copyAttributesFrom(const GlobalValue *Src) { const auto *GV = cast<GlobalObject>(Src); GlobalValue::copyAttributesFrom(GV); @@ -117,7 +133,7 @@ bool GlobalValue::isDeclaration() const { // Functions are definitions if they have a body. if (const Function *F = dyn_cast<Function>(this)) - return F->empty(); + return F->empty() && !F->isMaterializable(); // Aliases are always definitions. assert(isa<GlobalAlias>(this)); @@ -230,6 +246,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { GlobalObject::copyAttributesFrom(Src); const GlobalVariable *SrcVar = cast<GlobalVariable>(Src); setThreadLocalMode(SrcVar->getThreadLocalMode()); + setExternallyInitialized(SrcVar->isExternallyInitialized()); } diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index 435e54f0ea..a4c5d9766a 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -62,7 +62,8 @@ static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops, CallInst *IRBuilderBase:: CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag) { + bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, + MDNode *NoAliasTag) { Ptr = getCastedInt8PtrValue(Ptr); Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) }; Type *Tys[] = { Ptr->getType(), Size->getType() }; @@ -74,13 +75,20 @@ CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } CallInst *IRBuilderBase:: CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag) { + bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag, + MDNode *ScopeTag, MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); @@ -98,13 +106,20 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, // Set the TBAA Struct info if present. if (TBAAStructTag) CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } CallInst *IRBuilderBase:: CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag) { + bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, + MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); @@ -118,7 +133,13 @@ CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } @@ -151,3 +172,14 @@ CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) { Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end); return createCallHelper(TheFn, Ops, this); } + +CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { + assert(Cond->getType() == getInt1Ty() && + "an assumption condition must be of type i1"); + + Value *Ops[] = { Cond }; + Module *M = BB->getParent()->getParent(); + Value *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume); + return createCallHelper(FnAssume, Ops, this); +} + diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp index a3e1da3b18..16d874f32f 100644 --- a/lib/IR/InlineAsm.cpp +++ b/lib/IR/InlineAsm.cpp @@ -91,6 +91,10 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str, if (*I == '~') { Type = isClobber; ++I; + + // '{' must immediately follow '~'. + if (I != E && *I != '{') + return true; } else if (*I == '=') { ++I; Type = isOutput; diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp index 86421c4ae9..3ee66f5698 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -143,6 +143,11 @@ void Instruction::setFastMathFlags(FastMathFlags FMF) { cast<FPMathOperator>(this)->setFastMathFlags(FMF); } +void Instruction::copyFastMathFlags(FastMathFlags FMF) { + assert(isa<FPMathOperator>(this) && "copying fast-math flag on invalid op"); + cast<FPMathOperator>(this)->copyFastMathFlags(FMF); +} + /// Determine whether the unsafe-algebra flag is set. bool Instruction::hasUnsafeAlgebra() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); @@ -175,7 +180,7 @@ bool Instruction::hasAllowReciprocal() const { /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of -/// these flats. +/// these flags. FastMathFlags Instruction::getFastMathFlags() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->getFastMathFlags(); @@ -183,7 +188,7 @@ FastMathFlags Instruction::getFastMathFlags() const { /// Copy I's fast-math flags void Instruction::copyFastMathFlags(const Instruction *I) { - setFastMathFlags(I->getFastMathFlags()); + copyFastMathFlags(I->getFastMathFlags()); } @@ -438,6 +443,21 @@ bool Instruction::mayWriteToMemory() const { } } +bool Instruction::isAtomic() const { + switch (getOpcode()) { + default: + return false; + case Instruction::AtomicCmpXchg: + case Instruction::AtomicRMW: + case Instruction::Fence: + return true; + case Instruction::Load: + return cast<LoadInst>(this)->getOrdering() != NotAtomic; + case Instruction::Store: + return cast<StoreInst>(this)->getOrdering() != NotAtomic; + } +} + bool Instruction::mayThrow() const { if (const CallInst *CI = dyn_cast<CallInst>(this)) return !CI->doesNotThrow(); @@ -528,7 +548,7 @@ Instruction *Instruction::clone() const { // Otherwise, enumerate and copy over metadata from the old instruction to the // new one. - SmallVector<std::pair<unsigned, MDNode*>, 4> TheMDs; + SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs; getAllMetadataOtherThanDebugLoc(TheMDs); for (const auto &MD : TheMDs) New->setMetadata(MD.first, MD.second); diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index a5ceacb563..57a4f0b61d 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -364,8 +364,9 @@ bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind A) const { /// IsConstantOne - Return true only if val is constant int 1 static bool IsConstantOne(Value *val) { - assert(val && "IsConstantOne does not work with NULL val"); - return isa<ConstantInt>(val) && cast<ConstantInt>(val)->isOne(); + assert(val && "IsConstantOne does not work with nullptr val"); + const ConstantInt *CVal = dyn_cast<ConstantInt>(val); + return CVal && CVal->isOne(); } static Instruction *createMalloc(Instruction *InsertBefore, @@ -418,7 +419,7 @@ static Instruction *createMalloc(Instruction *InsertBefore, Value *MallocFunc = MallocF; if (!MallocFunc) // prototype malloc as "void *malloc(size_t)" - MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, NULL); + MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, nullptr); PointerType *AllocPtrType = PointerType::getUnqual(AllocTy); CallInst *MCall = nullptr; Instruction *Result = nullptr; @@ -491,7 +492,7 @@ static Instruction* createFree(Value* Source, Instruction *InsertBefore, Type *VoidTy = Type::getVoidTy(M->getContext()); Type *IntPtrTy = Type::getInt8PtrTy(M->getContext()); // prototype free as "void free(void*)" - Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, NULL); + Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, nullptr); CallInst* Result = nullptr; Value *PtrCast = Source; if (InsertBefore) { @@ -2030,6 +2031,39 @@ bool BinaryOperator::isExact() const { return cast<PossiblyExactOperator>(this)->isExact(); } +void BinaryOperator::copyIRFlags(const Value *V) { + // Copy the wrapping flags. + if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { + setHasNoSignedWrap(OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); + } + + // Copy the exact flag. + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) + setIsExact(PE->isExact()); + + // Copy the fast-math flags. + if (auto *FP = dyn_cast<FPMathOperator>(V)) + copyFastMathFlags(FP->getFastMathFlags()); +} + +void BinaryOperator::andIRFlags(const Value *V) { + if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { + setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); + } + + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) + setIsExact(isExact() & PE->isExact()); + + if (auto *FP = dyn_cast<FPMathOperator>(V)) { + FastMathFlags FM = getFastMathFlags(); + FM &= FP->getFastMathFlags(); + copyFastMathFlags(FM); + } +} + + //===----------------------------------------------------------------------===// // FPMathOperator Class //===----------------------------------------------------------------------===// @@ -2039,7 +2073,7 @@ bool BinaryOperator::isExact() const { /// default precision. float FPMathOperator::getFPAccuracy() const { const MDNode *MD = - cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath); + cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath); if (!MD) return 0.0; ConstantFP *Accuracy = cast<ConstantFP>(MD->getOperand(0)); @@ -2478,11 +2512,7 @@ CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, if (Ty->isIntOrIntVectorTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd); - Type *STy = S->getType(); - if (STy->getPointerAddressSpace() != Ty->getPointerAddressSpace()) - return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertAtEnd); - - return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd); + return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertAtEnd); } /// @brief Create a BitCast or a PtrToInt cast instruction @@ -2500,14 +2530,36 @@ CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty, if (Ty->isIntOrIntVectorTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore); - Type *STy = S->getType(); - if (STy->getPointerAddressSpace() != Ty->getPointerAddressSpace()) + return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertBefore); +} + +CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast( + Value *S, Type *Ty, + const Twine &Name, + BasicBlock *InsertAtEnd) { + assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"); + assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast"); + + if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace()) + return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertAtEnd); + + return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd); +} + +CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast( + Value *S, Type *Ty, + const Twine &Name, + Instruction *InsertBefore) { + assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"); + assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast"); + + if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace()) return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertBefore); return Create(Instruction::BitCast, S, Ty, Name, InsertBefore); } -CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty, +CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty, bool isSigned, const Twine &Name, Instruction *InsertBefore) { assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() && diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index de825f00b2..c62bc0936c 100644 --- a/lib/IR/LLVMContext.cpp +++ b/lib/IR/LLVMContext.cpp @@ -66,6 +66,33 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { unsigned InvariantLdId = getMDKindID("invariant.load"); assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted"); (void)InvariantLdId; + + // Create the 'alias.scope' metadata kind. + unsigned AliasScopeID = getMDKindID("alias.scope"); + assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted"); + (void)AliasScopeID; + + // Create the 'noalias' metadata kind. + unsigned NoAliasID = getMDKindID("noalias"); + assert(NoAliasID == MD_noalias && "noalias kind id drifted"); + (void)NoAliasID; + + // Create the 'nontemporal' metadata kind. + unsigned NonTemporalID = getMDKindID("nontemporal"); + assert(NonTemporalID == MD_nontemporal && "nontemporal kind id drifted"); + (void)NonTemporalID; + + // Create the 'llvm.mem.parallel_loop_access' metadata kind. + unsigned MemParallelLoopAccessID = getMDKindID("llvm.mem.parallel_loop_access"); + assert(MemParallelLoopAccessID == MD_mem_parallel_loop_access && + "mem_parallel_loop_access kind id drifted"); + (void)MemParallelLoopAccessID; + + + // Create the 'nonnull' metadata kind. + unsigned NonNullID = getMDKindID("nonnull"); + assert(NonNullID == MD_nonnull && "nonnull kind id drifted"); + (void)NonNullID; } LLVMContext::~LLVMContext() { delete pImpl; } @@ -102,9 +129,11 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const { } void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, - void *DiagnosticContext) { + void *DiagnosticContext, + bool RespectFilters) { pImpl->DiagnosticHandler = DiagnosticHandler; pImpl->DiagnosticContext = DiagnosticContext; + pImpl->RespectDiagnosticFilters = RespectFilters; } LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const { @@ -135,13 +164,7 @@ void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr)); } -void LLVMContext::diagnose(const DiagnosticInfo &DI) { - // If there is a report handler, use it. - if (pImpl->DiagnosticHandler) { - pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext); - return; - } - +static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { // Optimization remarks are selective. They need to check whether the regexp // pattern, passed via one of the -pass-remarks* flags, matches the name of // the pass that is emitting the diagnostic. If there is no match, ignore the @@ -149,19 +172,32 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) { switch (DI.getKind()) { case llvm::DK_OptimizationRemark: if (!cast<DiagnosticInfoOptimizationRemark>(DI).isEnabled()) - return; + return false; break; case llvm::DK_OptimizationRemarkMissed: if (!cast<DiagnosticInfoOptimizationRemarkMissed>(DI).isEnabled()) - return; + return false; break; case llvm::DK_OptimizationRemarkAnalysis: if (!cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI).isEnabled()) - return; + return false; break; default: break; } + return true; +} + +void LLVMContext::diagnose(const DiagnosticInfo &DI) { + // If there is a report handler, use it. + if (pImpl->DiagnosticHandler) { + if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) + pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext); + return; + } + + if (!isDiagnosticEnabled(DI)) + return; // Otherwise, print the message with a prefix based on the severity. std::string MsgStorage; @@ -217,9 +253,10 @@ unsigned LLVMContext::getMDKindID(StringRef Name) const { assert(isValidName(Name) && "Invalid MDNode name"); // If this is new, assign it its ID. - return - pImpl->CustomMDKindNames.GetOrCreateValue( - Name, pImpl->CustomMDKindNames.size()).second; + return pImpl->CustomMDKindNames.insert(std::make_pair( + Name, + pImpl->CustomMDKindNames.size())) + .first->second; } /// getHandlerNames - Populate client supplied smallvector using custome diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 4c2791f0a8..3fd0bb37a4 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -40,6 +40,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) InlineAsmDiagContext = nullptr; DiagnosticHandler = nullptr; DiagnosticContext = nullptr; + RespectDiagnosticFilters = false; YieldCallback = nullptr; YieldOpaqueHandle = nullptr; NamedStructTypesUniqueID = 0; @@ -75,7 +76,7 @@ LLVMContextImpl::~LLVMContextImpl() { // Free the constants. This is important to do here to ensure that they are // freed before the LeakDetector is torn down. std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(), - DropReferences()); + DropFirst()); std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(), DropFirst()); std::for_each(StructConstants.map_begin(), StructConstants.map_end(), @@ -121,20 +122,19 @@ LLVMContextImpl::~LLVMContextImpl() { // Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet // and the NonUniquedMDNodes sets, so copy the values out first. - SmallVector<MDNode*, 8> MDNodes; + SmallVector<GenericMDNode *, 8> MDNodes; MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size()); - for (FoldingSetIterator<MDNode> I = MDNodeSet.begin(), E = MDNodeSet.end(); - I != E; ++I) - MDNodes.push_back(&*I); + MDNodes.append(MDNodeSet.begin(), MDNodeSet.end()); MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end()); - for (SmallVectorImpl<MDNode *>::iterator I = MDNodes.begin(), - E = MDNodes.end(); I != E; ++I) - (*I)->destroy(); + for (GenericMDNode *I : MDNodes) + I->dropAllReferences(); + for (GenericMDNode *I : MDNodes) + delete I; assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() && "Destroying all MDNodes didn't empty the Context's sets."); // Destroy MDStrings. - DeleteContainerSeconds(MDStringCache); + MDStringCache.clear(); } // ConstantsContext anchors diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 808c239bff..e743ec3abc 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LLVMCONTEXT_IMPL_H -#define LLVM_LLVMCONTEXT_IMPL_H +#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H +#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H #include "AttributeImpl.h" #include "ConstantsContext.h" @@ -22,6 +22,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallPtrSet.h" @@ -150,7 +151,7 @@ struct FunctionTypeKeyInfo { ReturnType(R), Params(P), isVarArg(V) {} KeyTy(const FunctionType* FT) : ReturnType(FT->getReturnType()), - Params(ArrayRef<Type*>(FT->param_begin(), FT->param_end())), + Params(makeArrayRef(FT->param_begin(), FT->param_end())), isVarArg(FT->isVarArg()) {} bool operator==(const KeyTy& that) const { if (ReturnType != that.ReturnType) @@ -190,23 +191,52 @@ struct FunctionTypeKeyInfo { } }; -// Provide a FoldingSetTrait::Equals specialization for MDNode that can use a -// shortcut to avoid comparing all operands. -template<> struct FoldingSetTrait<MDNode> : DefaultFoldingSetTrait<MDNode> { - static bool Equals(const MDNode &X, const FoldingSetNodeID &ID, - unsigned IDHash, FoldingSetNodeID &TempID) { - assert(!X.isNotUniqued() && "Non-uniqued MDNode in FoldingSet?"); - // First, check if the cached hashes match. If they don't we can skip the - // expensive operand walk. - if (X.Hash != IDHash) - return false; +/// \brief DenseMapInfo for GenericMDNode. +/// +/// Note that we don't need the is-function-local bit, since that's implicit in +/// the operands. +struct GenericMDNodeInfo { + struct KeyTy { + ArrayRef<Value *> Ops; + unsigned Hash; + + KeyTy(ArrayRef<Value *> Ops) + : Ops(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {} + + KeyTy(GenericMDNode *N, SmallVectorImpl<Value *> &Storage) { + Storage.resize(N->getNumOperands()); + for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) + Storage[I] = N->getOperand(I); + Ops = Storage; + Hash = hash_combine_range(Ops.begin(), Ops.end()); + } - // If they match we have to compare the operands. - X.Profile(TempID); - return TempID == ID; + bool operator==(const GenericMDNode *RHS) const { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + if (Hash != RHS->getHash() || Ops.size() != RHS->getNumOperands()) + return false; + for (unsigned I = 0, E = Ops.size(); I != E; ++I) + if (Ops[I] != RHS->getOperand(I)) + return false; + return true; + } + }; + static inline GenericMDNode *getEmptyKey() { + return DenseMapInfo<GenericMDNode *>::getEmptyKey(); + } + static inline GenericMDNode *getTombstoneKey() { + return DenseMapInfo<GenericMDNode *>::getTombstoneKey(); } - static unsigned ComputeHash(const MDNode &X, FoldingSetNodeID &) { - return X.Hash; // Return cached hash. + static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; } + static unsigned getHashValue(const GenericMDNode *U) { + return U->getHash(); + } + static bool isEqual(const KeyTy &LHS, const GenericMDNode *RHS) { + return LHS == RHS; + } + static bool isEqual(const GenericMDNode *LHS, const GenericMDNode *RHS) { + return LHS == RHS; } }; @@ -244,6 +274,7 @@ public: LLVMContext::DiagnosticHandlerTy DiagnosticHandler; void *DiagnosticContext; + bool RespectDiagnosticFilters; LLVMContext::YieldCallbackTy YieldCallback; void *YieldOpaqueHandle; @@ -260,25 +291,25 @@ public: FoldingSet<AttributeSetImpl> AttrsLists; FoldingSet<AttributeSetNode> AttrsSetNodes; - StringMap<Value*> MDStringCache; + StringMap<MDString> MDStringCache; - FoldingSet<MDNode> MDNodeSet; + DenseSet<GenericMDNode *, GenericMDNodeInfo> MDNodeSet; // MDNodes may be uniqued or not uniqued. When they're not uniqued, they // aren't in the MDNodeSet, but they're still shared between objects, so no // one object can destroy them. This set allows us to at least destroy them // on Context destruction. - SmallPtrSet<MDNode*, 1> NonUniquedMDNodes; - + SmallPtrSet<GenericMDNode *, 1> NonUniquedMDNodes; + DenseMap<Type*, ConstantAggregateZero*> CAZConstants; - typedef ConstantAggrUniqueMap<ArrayType, ConstantArray> ArrayConstantsTy; + typedef ConstantUniqueMap<ConstantArray> ArrayConstantsTy; ArrayConstantsTy ArrayConstants; - typedef ConstantAggrUniqueMap<StructType, ConstantStruct> StructConstantsTy; + typedef ConstantUniqueMap<ConstantStruct> StructConstantsTy; StructConstantsTy StructConstants; - typedef ConstantAggrUniqueMap<VectorType, ConstantVector> VectorConstantsTy; + typedef ConstantUniqueMap<ConstantVector> VectorConstantsTy; VectorConstantsTy VectorConstants; DenseMap<PointerType*, ConstantPointerNull*> CPNConstants; @@ -289,12 +320,10 @@ public: DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *> BlockAddresses; - ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr> - ExprConstants; + ConstantUniqueMap<ConstantExpr> ExprConstants; + + ConstantUniqueMap<InlineAsm> InlineAsms; - ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType, - InlineAsm> InlineAsms; - ConstantInt *TheTrueVal; ConstantInt *TheFalseVal; diff --git a/lib/IR/LeaksContext.h b/lib/IR/LeaksContext.h index 52ac170459..3e485abdfd 100644 --- a/lib/IR/LeaksContext.h +++ b/lib/IR/LeaksContext.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_LEAKSCONTEXT_H -#define LLVM_IR_LEAKSCONTEXT_H +#ifndef LLVM_LIB_IR_LEAKSCONTEXT_H +#define LLVM_LIB_IR_LEAKSCONTEXT_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Value.h" @@ -95,4 +95,4 @@ private: } -#endif // LLVM_IR_LEAKSCONTEXT_H +#endif diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp index d3f3482dc0..28fa74cbfd 100644 --- a/lib/IR/LegacyPassManager.cpp +++ b/lib/IR/LegacyPassManager.cpp @@ -573,9 +573,8 @@ void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses, return; SmallPtrSet<Pass *, 8> &LU = DMI->second; - for (SmallPtrSet<Pass *, 8>::iterator I = LU.begin(), - E = LU.end(); I != E; ++I) { - LastUses.push_back(*I); + for (Pass *LUP : LU) { + LastUses.push_back(LUP); } } @@ -1404,11 +1403,8 @@ void FunctionPassManager::add(Pass *P) { /// so, return true. /// bool FunctionPassManager::run(Function &F) { - if (F.isMaterializable()) { - std::string errstr; - if (F.Materialize(&errstr)) - report_fatal_error("Error reading bitcode file: " + Twine(errstr)); - } + if (std::error_code EC = F.materialize()) + report_fatal_error("Error reading bitcode file: " + EC.message()); return FPM->run(F); } @@ -1684,7 +1680,7 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { if (!FoundPass) { FoundPass = RequiredPass; // This should be guaranteed to add RequiredPass to the passmanager given - // that we checked for an avaiable analysis above. + // that we checked for an available analysis above. FPP->add(RequiredPass); } // Register P as the last user of FoundPass or RequiredPass. diff --git a/lib/IR/MDBuilder.cpp b/lib/IR/MDBuilder.cpp index 65cdf38852..3ec613c2f6 100644 --- a/lib/IR/MDBuilder.cpp +++ b/lib/IR/MDBuilder.cpp @@ -60,10 +60,17 @@ MDNode *MDBuilder::createRange(const APInt &Lo, const APInt &Hi) { return MDNode::get(Context, Range); } -MDNode *MDBuilder::createAnonymousTBAARoot() { +MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) { // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value *>()); - MDNode *Root = MDNode::get(Context, Dummy); + MDNode *Dummy = MDNode::getTemporary(Context, None); + + SmallVector<Value *, 3> Args(1, Dummy); + if (Extra) + Args.push_back(Extra); + if (!Name.empty()) + Args.push_back(createString(Name)); + MDNode *Root = MDNode::get(Context, Args); + // At this point we have // !0 = metadata !{} <- dummy // !1 = metadata !{metadata !0} <- root @@ -93,6 +100,15 @@ MDNode *MDBuilder::createTBAANode(StringRef Name, MDNode *Parent, } } +MDNode *MDBuilder::createAliasScopeDomain(StringRef Name) { + return MDNode::get(Context, createString(Name)); +} + +MDNode *MDBuilder::createAliasScope(StringRef Name, MDNode *Domain) { + Value *Ops[2] = { createString(Name), Domain }; + return MDNode::get(Context, Ops); +} + /// \brief Return metadata for a tbaa.struct node with the given /// struct field descriptions. MDNode *MDBuilder::createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { diff --git a/lib/IR/Mangler.cpp b/lib/IR/Mangler.cpp index 27d973b94f..5eeb7978e2 100644 --- a/lib/IR/Mangler.cpp +++ b/lib/IR/Mangler.cpp @@ -22,23 +22,25 @@ using namespace llvm; static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName, Mangler::ManglerPrefixTy PrefixTy, - const DataLayout &DL, bool UseAt) { + const DataLayout &DL, char Prefix) { SmallString<256> TmpData; StringRef Name = GVName.toStringRef(TmpData); assert(!Name.empty() && "getNameWithPrefix requires non-empty name"); + // No need to do anything special if the global has the special "do not + // mangle" flag in the name. + if (Name[0] == '\1') { + OS << Name.substr(1); + return; + } + if (PrefixTy == Mangler::Private) OS << DL.getPrivateGlobalPrefix(); else if (PrefixTy == Mangler::LinkerPrivate) OS << DL.getLinkerPrivateGlobalPrefix(); - if (UseAt) { - OS << '@'; - } else { - char Prefix = DL.getGlobalPrefix(); - if (Prefix != '\0') - OS << Prefix; - } + if (Prefix != '\0') + OS << Prefix; // If this is a simple string that doesn't need escaping, just append it. OS << Name; @@ -46,7 +48,8 @@ static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName, void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName, ManglerPrefixTy PrefixTy) const { - return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, false); + char Prefix = DL->getGlobalPrefix(); + return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, Prefix); } void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, @@ -56,11 +59,21 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, return getNameWithPrefix(OS, GVName, PrefixTy); } -/// AddFastCallStdCallSuffix - Microsoft fastcall and stdcall functions require -/// a suffix on their name indicating the number of words of arguments they -/// take. -static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F, - const DataLayout &TD) { +static bool hasByteCountSuffix(CallingConv::ID CC) { + switch (CC) { + case CallingConv::X86_FastCall: + case CallingConv::X86_StdCall: + case CallingConv::X86_VectorCall: + return true; + default: + return false; + } +} + +/// Microsoft fastcall and stdcall functions require a suffix on their name +/// indicating the number of words of arguments they take. +static void addByteCountSuffix(raw_ostream &OS, const Function *F, + const DataLayout &TD) { // Calculate arguments size total. unsigned ArgWords = 0; for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); @@ -69,8 +82,9 @@ static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F, // 'Dereference' type in case of byval or inalloca parameter attribute. if (AI->hasByValOrInAllocaAttr()) Ty = cast<PointerType>(Ty)->getElementType(); - // Size should be aligned to DWORD boundary - ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4; + // Size should be aligned to pointer size. + unsigned PtrSize = TD.getPointerSize(); + ArgWords += RoundUpToAlignment(TD.getTypeAllocSize(Ty), PtrSize); } OS << '@' << ArgWords; @@ -99,41 +113,41 @@ void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, } StringRef Name = GV->getName(); - - // No need to do anything special if the global has the special "do not - // mangle" flag in the name. - if (Name[0] == '\1') { - OS << Name.substr(1); - return; - } - - bool UseAt = false; - const Function *MSFunc = nullptr; - CallingConv::ID CC; - if (DL->hasMicrosoftFastStdCallMangling()) { - if ((MSFunc = dyn_cast<Function>(GV))) { - CC = MSFunc->getCallingConv(); - // fastcall functions need to start with @ instead of _. - if (CC == CallingConv::X86_FastCall) - UseAt = true; - } + char Prefix = DL->getGlobalPrefix(); + + // Mangle functions with Microsoft calling conventions specially. Only do + // this mangling for x86_64 vectorcall and 32-bit x86. + const Function *MSFunc = dyn_cast<Function>(GV); + if (Name.startswith("\01")) + MSFunc = nullptr; // Don't mangle when \01 is present. + CallingConv::ID CC = + MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C; + if (!DL->hasMicrosoftFastStdCallMangling() && + CC != CallingConv::X86_VectorCall) + MSFunc = nullptr; + if (MSFunc) { + if (CC == CallingConv::X86_FastCall) + Prefix = '@'; // fastcall functions have an @ prefix instead of _. + else if (CC == CallingConv::X86_VectorCall) + Prefix = '\0'; // vectorcall functions have no prefix. } - getNameWithPrefixx(OS, Name, PrefixTy, *DL, UseAt); + getNameWithPrefixx(OS, Name, PrefixTy, *DL, Prefix); if (!MSFunc) return; - // If we are supposed to add a microsoft-style suffix for stdcall/fastcall, - // add it. - // fastcall and stdcall functions usually need @42 at the end to specify - // the argument info. + // If we are supposed to add a microsoft-style suffix for stdcall, fastcall, + // or vectorcall, add it. These functions have a suffix of @N where N is the + // cumulative byte size of all of the parameters to the function in decimal. + if (CC == CallingConv::X86_VectorCall) + OS << '@'; // vectorcall functions use a double @ suffix. FunctionType *FT = MSFunc->getFunctionType(); - if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) && + if (hasByteCountSuffix(CC) && // "Pure" variadic functions do not receive @0 suffix. (!FT->isVarArg() || FT->getNumParams() == 0 || (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr()))) - AddFastCallStdCallSuffix(OS, MSFunc, *DL); + addByteCountSuffix(OS, MSFunc, *DL); } void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 59137e47fa..27ba9f7a87 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -25,25 +25,34 @@ #include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" + using namespace llvm; +Metadata::Metadata(LLVMContext &Context, unsigned ID) + : Value(Type::getMetadataTy(Context), ID) {} + //===----------------------------------------------------------------------===// // MDString implementation. // void MDString::anchor() { } -MDString::MDString(LLVMContext &C) - : Value(Type::getMetadataTy(C), Value::MDStringVal) {} - MDString *MDString::get(LLVMContext &Context, StringRef Str) { - LLVMContextImpl *pImpl = Context.pImpl; - StringMapEntry<Value*> &Entry = - pImpl->MDStringCache.GetOrCreateValue(Str); - Value *&S = Entry.getValue(); - if (!S) S = new MDString(Context); - S->setValueName(&Entry); - return cast<MDString>(S); + auto &Store = Context.pImpl->MDStringCache; + auto I = Store.find(Str); + if (I != Store.end()) + return &I->second; + + auto *Entry = + StringMapEntry<MDString>::Create(Str, Store.getAllocator(), Context); + bool WasInserted = Store.insert(Entry); + (void)WasInserted; + assert(WasInserted && "Expected entry to be inserted"); + return &Entry->second; +} + +StringRef MDString::getString() const { + return StringMapEntry<MDString>::GetStringMapEntryFromValue(*this).first(); } //===----------------------------------------------------------------------===// @@ -57,26 +66,25 @@ class MDNodeOperand : public CallbackVH { MDNodeOperand *Cur = this; while (Cur->getValPtrInt() != 1) - --Cur; + ++Cur; assert(Cur->getValPtrInt() == 1 && - "Couldn't find the beginning of the operand list!"); - return reinterpret_cast<MDNode*>(Cur) - 1; + "Couldn't find the end of the operand list!"); + return reinterpret_cast<MDNode *>(Cur + 1); } public: - MDNodeOperand(Value *V) : CallbackVH(V) {} + MDNodeOperand() {} virtual ~MDNodeOperand(); void set(Value *V) { - unsigned IsFirst = this->getValPtrInt(); + unsigned IsLast = this->getValPtrInt(); this->setValPtr(V); - this->setAsFirstOperand(IsFirst); + this->setAsLastOperand(IsLast); } - /// setAsFirstOperand - Accessor method to mark the operand as the first in - /// the list. - void setAsFirstOperand(unsigned V) { this->setValPtrInt(V); } + /// \brief Accessor method to mark the operand as the first in the list. + void setAsLastOperand(unsigned I) { this->setValPtrInt(I); } void deleted() override; void allUsesReplacedWith(Value *NV) override; @@ -98,12 +106,11 @@ void MDNodeOperand::allUsesReplacedWith(Value *NV) { // MDNode implementation. // -/// getOperandPtr - Helper function to get the MDNodeOperand's coallocated on -/// the end of the MDNode. +/// \brief Get the MDNodeOperand's coallocated on the end of the MDNode. static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) { // Use <= instead of < to permit a one-past-the-end address. assert(Op <= N->getNumOperands() && "Invalid operand number"); - return reinterpret_cast<MDNodeOperand*>(N + 1) + Op; + return reinterpret_cast<MDNodeOperand *>(N) - N->getNumOperands() + Op; } void MDNode::replaceOperandWith(unsigned i, Value *Val) { @@ -111,40 +118,54 @@ void MDNode::replaceOperandWith(unsigned i, Value *Val) { replaceOperand(Op, Val); } -MDNode::MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal) -: Value(Type::getMetadataTy(C), Value::MDNodeVal) { +void *MDNode::operator new(size_t Size, unsigned NumOps) { + void *Ptr = ::operator new(Size + NumOps * sizeof(MDNodeOperand)); + MDNodeOperand *Op = static_cast<MDNodeOperand *>(Ptr); + if (NumOps) { + MDNodeOperand *Last = Op + NumOps; + for (; Op != Last; ++Op) + new (Op) MDNodeOperand(); + (Op - 1)->setAsLastOperand(1); + } + return Op; +} + +void MDNode::operator delete(void *Mem) { + MDNode *N = static_cast<MDNode *>(Mem); + MDNodeOperand *Op = static_cast<MDNodeOperand *>(Mem); + for (unsigned I = 0, E = N->NumOperands; I != E; ++I) + (--Op)->~MDNodeOperand(); + ::operator delete(Op); +} + +MDNode::MDNode(LLVMContext &C, unsigned ID, ArrayRef<Value *> Vals, + bool isFunctionLocal) + : Metadata(C, ID) { NumOperands = Vals.size(); if (isFunctionLocal) setValueSubclassData(getSubclassDataFromValue() | FunctionLocalBit); - // Initialize the operand list, which is co-allocated on the end of the node. + // Initialize the operand list. unsigned i = 0; - for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands; - Op != E; ++Op, ++i) { - new (Op) MDNodeOperand(Vals[i]); - - // Mark the first MDNodeOperand as being the first in the list of operands. - if (i == 0) - Op->setAsFirstOperand(1); - } + for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op + NumOperands; + Op != E; ++Op, ++i) + Op->set(Vals[i]); } -/// ~MDNode - Destroy MDNode. -MDNode::~MDNode() { - assert((getSubclassDataFromValue() & DestroyFlag) != 0 && - "Not being destroyed through destroy()?"); +GenericMDNode::~GenericMDNode() { LLVMContextImpl *pImpl = getType()->getContext().pImpl; if (isNotUniqued()) { pImpl->NonUniquedMDNodes.erase(this); } else { - pImpl->MDNodeSet.RemoveNode(this); + pImpl->MDNodeSet.erase(this); } +} - // Destroy the operands. - for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands; +void GenericMDNode::dropAllReferences() { + for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op + NumOperands; Op != E; ++Op) - Op->~MDNodeOperand(); + Op->set(nullptr); } static const Function *getFunctionForValue(Value *V) { @@ -201,16 +222,7 @@ const Function *MDNode::getFunction() const { #endif } -// destroy - Delete this node. Only when there are no uses. -void MDNode::destroy() { - setValueSubclassData(getSubclassDataFromValue() | DestroyFlag); - // Placement delete, then free the memory. - this->~MDNode(); - free(this); -} - -/// isFunctionLocalValue - Return true if this is a value that would require a -/// function-local MDNode. +/// \brief Check if the Value would require a function-local MDNode. static bool isFunctionLocalValue(Value *V) { return isa<Instruction>(V) || isa<Argument>(V) || isa<BasicBlock>(V) || (isa<MDNode>(V) && cast<MDNode>(V)->isFunctionLocal()); @@ -218,21 +230,14 @@ static bool isFunctionLocalValue(Value *V) { MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals, FunctionLocalness FL, bool Insert) { - LLVMContextImpl *pImpl = Context.pImpl; - - // Add all the operand pointers. Note that we don't have to add the - // isFunctionLocal bit because that's implied by the operands. - // Note that if the operands are later nulled out, the node will be - // removed from the uniquing map. - FoldingSetNodeID ID; - for (Value *V : Vals) - ID.AddPointer(V); - - void *InsertPoint; - MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); + auto &Store = Context.pImpl->MDNodeSet; - if (N || !Insert) - return N; + GenericMDNodeInfo::KeyTy Key(Vals); + auto I = Store.find_as(Key); + if (I != Store.end()) + return *I; + if (!Insert) + return nullptr; bool isFunctionLocal = false; switch (FL) { @@ -254,15 +259,11 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals, } // Coallocate space for the node and Operands together, then placement new. - void *Ptr = malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand)); - N = new (Ptr) MDNode(Context, Vals, isFunctionLocal); - - // Cache the operand hash. - N->Hash = ID.ComputeHash(); - - // InsertPoint will have been set by the FindNodeOrInsertPos call. - pImpl->MDNodeSet.InsertNode(N, InsertPoint); + GenericMDNode *N = + new (Vals.size()) GenericMDNode(Context, Vals, isFunctionLocal); + N->Hash = Key.Hash; + Store.insert(N); return N; } @@ -281,48 +282,33 @@ MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals) { } MDNode *MDNode::getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals) { - MDNode *N = - (MDNode *)malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand)); - N = new (N) MDNode(Context, Vals, FL_No); - N->setValueSubclassData(N->getSubclassDataFromValue() | - NotUniquedBit); + MDNode *N = new (Vals.size()) MDNodeFwdDecl(Context, Vals, FL_No); + N->setValueSubclassData(N->getSubclassDataFromValue() | NotUniquedBit); LeakDetector::addGarbageObject(N); return N; } void MDNode::deleteTemporary(MDNode *N) { assert(N->use_empty() && "Temporary MDNode has uses!"); - assert(!N->getContext().pImpl->MDNodeSet.RemoveNode(N) && - "Deleting a non-temporary uniqued node!"); - assert(!N->getContext().pImpl->NonUniquedMDNodes.erase(N) && - "Deleting a non-temporary non-uniqued node!"); + assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration"); assert((N->getSubclassDataFromValue() & NotUniquedBit) && "Temporary MDNode does not have NotUniquedBit set!"); - assert((N->getSubclassDataFromValue() & DestroyFlag) == 0 && - "Temporary MDNode has DestroyFlag set!"); LeakDetector::removeGarbageObject(N); - N->destroy(); + delete cast<MDNodeFwdDecl>(N); } -/// getOperand - Return specified operand. +/// \brief Return specified operand. Value *MDNode::getOperand(unsigned i) const { assert(i < getNumOperands() && "Invalid operand number"); return *getOperandPtr(const_cast<MDNode*>(this), i); } -void MDNode::Profile(FoldingSetNodeID &ID) const { - // Add all the operand pointers. Note that we don't have to add the - // isFunctionLocal bit because that's implied by the operands. - // Note that if the operands are later nulled out, the node will be - // removed from the uniquing map. - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - ID.AddPointer(getOperand(i)); -} - void MDNode::setIsNotUniqued() { setValueSubclassData(getSubclassDataFromValue() | NotUniquedBit); LLVMContextImpl *pImpl = getType()->getContext().pImpl; - pImpl->NonUniquedMDNodes.insert(this); + auto *G = cast<GenericMDNode>(this); + G->Hash = 0; + pImpl->NonUniquedMDNodes.insert(G); } // Replace value from this node's operand list. @@ -350,44 +336,45 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { if (From == To) return; - // Update the operand. - Op->set(To); - // If this node is already not being uniqued (because one of the operands // already went to null), then there is nothing else to do here. - if (isNotUniqued()) return; + if (isNotUniqued()) { + Op->set(To); + return; + } - LLVMContextImpl *pImpl = getType()->getContext().pImpl; + auto &Store = getContext().pImpl->MDNodeSet; + auto *N = cast<GenericMDNode>(this); - // Remove "this" from the context map. FoldingSet doesn't have to reprofile - // this node to remove it, so we don't care what state the operands are in. - pImpl->MDNodeSet.RemoveNode(this); + // Remove "this" from the context map. + Store.erase(N); + + // Update the operand. + Op->set(To); // If we are dropping an argument to null, we choose to not unique the MDNode // anymore. This commonly occurs during destruction, and uniquing these // brings little reuse. Also, this means we don't need to include - // isFunctionLocal bits in FoldingSetNodeIDs for MDNodes. + // isFunctionLocal bits in the hash for MDNodes. if (!To) { setIsNotUniqued(); return; } - // Now that the node is out of the folding set, get ready to reinsert it. - // First, check to see if another node with the same operands already exists - // in the set. If so, then this node is redundant. - FoldingSetNodeID ID; - Profile(ID); - void *InsertPoint; - if (MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint)) { - replaceAllUsesWith(N); - destroy(); + // Now that the node is out of the table, get ready to reinsert it. First, + // check to see if another node with the same operands already exists in the + // set. If so, then this node is redundant. + SmallVector<Value *, 8> Vals; + GenericMDNodeInfo::KeyTy Key(N, Vals); + auto I = Store.find_as(Key); + if (I != Store.end()) { + N->replaceAllUsesWith(*I); + delete N; return; } - // Cache the operand hash. - Hash = ID.ComputeHash(); - // InsertPoint will have been set by the FindNodeOrInsertPos call. - pImpl->MDNodeSet.InsertNode(this, InsertPoint); + N->Hash = Key.Hash; + Store.insert(N); // If this MDValue was previously function-local but no longer is, clear // its function-local flag. @@ -406,6 +393,41 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { } } +MDNode *MDNode::concatenate(MDNode *A, MDNode *B) { + if (!A) + return B; + if (!B) + return A; + + SmallVector<Value *, 4> Vals(A->getNumOperands() + + B->getNumOperands()); + + unsigned j = 0; + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) + Vals[j++] = A->getOperand(i); + for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i) + Vals[j++] = B->getOperand(i); + + return MDNode::get(A->getContext(), Vals); +} + +MDNode *MDNode::intersect(MDNode *A, MDNode *B) { + if (!A || !B) + return nullptr; + + SmallVector<Value *, 4> Vals; + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) { + Value *V = A->getOperand(i); + for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j) + if (V == B->getOperand(j)) { + Vals.push_back(V); + break; + } + } + + return MDNode::get(A->getContext(), Vals); +} + MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) { if (!A || !B) return nullptr; @@ -524,49 +546,41 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) { // static SmallVector<TrackingVH<MDNode>, 4> &getNMDOps(void *Operands) { - return *(SmallVector<TrackingVH<MDNode>, 4>*)Operands; + return *(SmallVector<TrackingVH<MDNode>, 4> *)Operands; } NamedMDNode::NamedMDNode(const Twine &N) - : Name(N.str()), Parent(nullptr), - Operands(new SmallVector<TrackingVH<MDNode>, 4>()) { -} + : Name(N.str()), Parent(nullptr), + Operands(new SmallVector<TrackingVH<MDNode>, 4>()) {} NamedMDNode::~NamedMDNode() { dropAllReferences(); delete &getNMDOps(Operands); } -/// getNumOperands - Return number of NamedMDNode operands. unsigned NamedMDNode::getNumOperands() const { return (unsigned)getNMDOps(Operands).size(); } -/// getOperand - Return specified operand. MDNode *NamedMDNode::getOperand(unsigned i) const { assert(i < getNumOperands() && "Invalid Operand number!"); - return dyn_cast<MDNode>(&*getNMDOps(Operands)[i]); + return &*getNMDOps(Operands)[i]; } -/// addOperand - Add metadata Operand. void NamedMDNode::addOperand(MDNode *M) { assert(!M->isFunctionLocal() && "NamedMDNode operands must not be function-local!"); getNMDOps(Operands).push_back(TrackingVH<MDNode>(M)); } -/// eraseFromParent - Drop all references and remove the node from parent -/// module. void NamedMDNode::eraseFromParent() { getParent()->eraseNamedMetadata(this); } -/// dropAllReferences - Remove all uses and clear node vector. void NamedMDNode::dropAllReferences() { getNMDOps(Operands).clear(); } -/// getName - Return a constant reference to this named metadata's name. StringRef NamedMDNode::getName() const { return StringRef(Name); } @@ -576,7 +590,8 @@ StringRef NamedMDNode::getName() const { // void Instruction::setMetadata(StringRef Kind, MDNode *Node) { - if (!Node && !hasMetadata()) return; + if (!Node && !hasMetadata()) + return; setMetadata(getContext().getMDKindID(Kind), Node); } @@ -632,7 +647,8 @@ void Instruction::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) { /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. void Instruction::setMetadata(unsigned KindID, MDNode *Node) { - if (!Node && !hasMetadata()) return; + if (!Node && !hasMetadata()) + return; // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) { @@ -687,6 +703,12 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) { // Otherwise, removing an entry that doesn't exist on the instruction. } +void Instruction::setAAMetadata(const AAMDNodes &N) { + setMetadata(LLVMContext::MD_tbaa, N.TBAA); + setMetadata(LLVMContext::MD_alias_scope, N.Scope); + setMetadata(LLVMContext::MD_noalias, N.NoAlias); +} + MDNode *Instruction::getMetadataImpl(unsigned KindID) const { // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) @@ -703,8 +725,8 @@ MDNode *Instruction::getMetadataImpl(unsigned KindID) const { return nullptr; } -void Instruction::getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, - MDNode*> > &Result) const { +void Instruction::getAllMetadataImpl( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const { Result.clear(); // Handle 'dbg' as a special case since it is not stored in the hash table. @@ -728,9 +750,8 @@ void Instruction::getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, array_pod_sort(Result.begin(), Result.end()); } -void Instruction:: -getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned, - MDNode*> > &Result) const { +void Instruction::getAllMetadataOtherThanDebugLocImpl( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const { Result.clear(); assert(hasMetadataHashEntry() && getContext().pImpl->MetadataStore.count(this) && diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index f1b1f9a2ac..14e534b8b1 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -259,6 +259,17 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) { NamedMDList.erase(NMD); } +bool Module::isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB) { + if (ConstantInt *Behavior = dyn_cast<ConstantInt>(V)) { + uint64_t Val = Behavior->getLimitedValue(); + if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) { + MFB = static_cast<ModFlagBehavior>(Val); + return true; + } + } + return false; +} + /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void Module:: getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { @@ -266,15 +277,15 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { if (!ModFlags) return; for (const MDNode *Flag : ModFlags->operands()) { - if (Flag->getNumOperands() >= 3 && isa<ConstantInt>(Flag->getOperand(0)) && + ModFlagBehavior MFB; + if (Flag->getNumOperands() >= 3 && + isValidModFlagBehavior(Flag->getOperand(0), MFB) && isa<MDString>(Flag->getOperand(1))) { // Check the operands of the MDNode before accessing the operands. // The verifier will actually catch these failures. - ConstantInt *Behavior = cast<ConstantInt>(Flag->getOperand(0)); MDString *Key = cast<MDString>(Flag->getOperand(1)); Value *Val = Flag->getOperand(2); - Flags.push_back(ModuleFlagEntry(ModFlagBehavior(Behavior->getZExtValue()), - Key, Val)); + Flags.push_back(ModuleFlagEntry(MFB, Key, Val)); } } } @@ -378,28 +389,17 @@ void Module::setMaterializer(GVMaterializer *GVM) { Materializer.reset(GVM); } -bool Module::isMaterializable(const GlobalValue *GV) const { - if (Materializer) - return Materializer->isMaterializable(GV); - return false; -} - bool Module::isDematerializable(const GlobalValue *GV) const { if (Materializer) return Materializer->isDematerializable(GV); return false; } -bool Module::Materialize(GlobalValue *GV, std::string *ErrInfo) { +std::error_code Module::materialize(GlobalValue *GV) { if (!Materializer) - return false; + return std::error_code(); - std::error_code EC = Materializer->Materialize(GV); - if (!EC) - return false; - if (ErrInfo) - *ErrInfo = EC.message(); - return true; + return Materializer->materialize(GV); } void Module::Dematerialize(GlobalValue *GV) { @@ -413,13 +413,10 @@ std::error_code Module::materializeAll() { return Materializer->MaterializeModule(this); } -std::error_code Module::materializeAllPermanently(bool ReleaseBuffer) { +std::error_code Module::materializeAllPermanently() { if (std::error_code EC = materializeAll()) return EC; - if (ReleaseBuffer) - Materializer->releaseBuffer(); - Materializer.reset(); return std::error_code(); } @@ -455,9 +452,20 @@ unsigned Module::getDwarfVersion() const { } Comdat *Module::getOrInsertComdat(StringRef Name) { - Comdat C; - StringMapEntry<Comdat> &Entry = - ComdatSymTab.GetOrCreateValue(Name, std::move(C)); + auto &Entry = *ComdatSymTab.insert(std::make_pair(Name, Comdat())).first; Entry.second.Name = &Entry; return &Entry.second; } + +PICLevel::Level Module::getPICLevel() const { + Value *Val = getModuleFlag("PIC Level"); + + if (Val == NULL) + return PICLevel::Default; + + return static_cast<PICLevel::Level>(cast<ConstantInt>(Val)->getZExtValue()); +} + +void Module::setPICLevel(PICLevel::Level PL) { + addModuleFlag(ModFlagBehavior::Error, "PIC Level", PL); +} diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 0defb6ab3e..2e2a7cb495 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -53,7 +53,7 @@ ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) { // If we don't have a cached result for this module, look up the pass and run // it to produce a result, which we then add to the cache. if (Inserted) - RI->second = std::move(lookupPass(PassID).run(M, this)); + RI->second = lookupPass(PassID).run(M, this); return *RI->second; } diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp index 91940a9c7f..b879fef3f4 100644 --- a/lib/IR/PassRegistry.cpp +++ b/lib/IR/PassRegistry.cpp @@ -36,8 +36,7 @@ PassRegistry *PassRegistry::getPassRegistry() { // Accessors // -PassRegistry::~PassRegistry() { -} +PassRegistry::~PassRegistry() {} const PassInfo *PassRegistry::getPassInfo(const void *TI) const { sys::SmartScopedReader<true> Guard(Lock); @@ -58,77 +57,62 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { sys::SmartScopedWriter<true> Guard(Lock); bool Inserted = - PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; + PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second; assert(Inserted && "Pass registered multiple times!"); (void)Inserted; PassInfoStringMap[PI.getPassArgument()] = &PI; - + // Notify any listeners. - for (std::vector<PassRegistrationListener*>::iterator - I = Listeners.begin(), E = Listeners.end(); I != E; ++I) - (*I)->passRegistered(&PI); - - if (ShouldFree) ToFree.push_back(std::unique_ptr<const PassInfo>(&PI)); -} + for (auto *Listener : Listeners) + Listener->passRegistered(&PI); -void PassRegistry::unregisterPass(const PassInfo &PI) { - sys::SmartScopedWriter<true> Guard(Lock); - MapType::iterator I = PassInfoMap.find(PI.getTypeInfo()); - assert(I != PassInfoMap.end() && "Pass registered but not in map!"); - - // Remove pass from the map. - PassInfoMap.erase(I); - PassInfoStringMap.erase(PI.getPassArgument()); + if (ShouldFree) + ToFree.push_back(std::unique_ptr<const PassInfo>(&PI)); } void PassRegistry::enumerateWith(PassRegistrationListener *L) { sys::SmartScopedReader<true> Guard(Lock); - for (auto I = PassInfoMap.begin(), E = PassInfoMap.end(); I != E; ++I) - L->passEnumerate(I->second); + for (auto PassInfoPair : PassInfoMap) + L->passEnumerate(PassInfoPair.second); } - /// Analysis Group Mechanisms. -void PassRegistry::registerAnalysisGroup(const void *InterfaceID, +void PassRegistry::registerAnalysisGroup(const void *InterfaceID, const void *PassID, - PassInfo& Registeree, - bool isDefault, + PassInfo &Registeree, bool isDefault, bool ShouldFree) { - PassInfo *InterfaceInfo = const_cast<PassInfo*>(getPassInfo(InterfaceID)); + PassInfo *InterfaceInfo = const_cast<PassInfo *>(getPassInfo(InterfaceID)); if (!InterfaceInfo) { // First reference to Interface, register it now. registerPass(Registeree); InterfaceInfo = &Registeree; } - assert(Registeree.isAnalysisGroup() && + assert(Registeree.isAnalysisGroup() && "Trying to join an analysis group that is a normal pass!"); if (PassID) { - PassInfo *ImplementationInfo = const_cast<PassInfo*>(getPassInfo(PassID)); + PassInfo *ImplementationInfo = const_cast<PassInfo *>(getPassInfo(PassID)); assert(ImplementationInfo && "Must register pass before adding to AnalysisGroup!"); sys::SmartScopedWriter<true> Guard(Lock); - + // Make sure we keep track of the fact that the implementation implements // the interface. ImplementationInfo->addInterfaceImplemented(InterfaceInfo); - AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo]; - assert(AGI.Implementations.count(ImplementationInfo) == 0 && - "Cannot add a pass to the same analysis group more than once!"); - AGI.Implementations.insert(ImplementationInfo); if (isDefault) { assert(InterfaceInfo->getNormalCtor() == nullptr && "Default implementation for analysis group already specified!"); - assert(ImplementationInfo->getNormalCtor() && - "Cannot specify pass as default if it does not have a default ctor"); + assert( + ImplementationInfo->getNormalCtor() && + "Cannot specify pass as default if it does not have a default ctor"); InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor()); InterfaceInfo->setTargetMachineCtor( ImplementationInfo->getTargetMachineCtor()); } } - + if (ShouldFree) ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree)); } @@ -140,7 +124,7 @@ void PassRegistry::addRegistrationListener(PassRegistrationListener *L) { void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) { sys::SmartScopedWriter<true> Guard(Lock); - + auto I = std::find(Listeners.begin(), Listeners.end(), L); Listeners.erase(I); } diff --git a/lib/IR/SymbolTableListTraitsImpl.h b/lib/IR/SymbolTableListTraitsImpl.h index 8302597c94..a18f98261a 100644 --- a/lib/IR/SymbolTableListTraitsImpl.h +++ b/lib/IR/SymbolTableListTraitsImpl.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYMBOLTABLELISTTRAITS_IMPL_H -#define LLVM_SYMBOLTABLELISTTRAITS_IMPL_H +#ifndef LLVM_LIB_IR_SYMBOLTABLELISTTRAITSIMPL_H +#define LLVM_LIB_IR_SYMBOLTABLELISTTRAITSIMPL_H #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/ValueSymbolTable.h" diff --git a/lib/IR/Type.cpp b/lib/IR/Type.cpp index 1efde47b85..0458b5f35b 100644 --- a/lib/IR/Type.cpp +++ b/lib/IR/Type.cpp @@ -89,9 +89,13 @@ bool Type::canLosslesslyBitCastTo(Type *Ty) const { // At this point we have only various mismatches of the first class types // remaining and ptr->ptr. Just select the lossless conversions. Everything - // else is not lossless. - if (this->isPointerTy()) - return Ty->isPointerTy(); + // else is not lossless. Conservatively assume we can't losslessly convert + // between pointers with different address spaces. + if (const PointerType *PTy = dyn_cast<PointerType>(this)) { + if (const PointerType *OtherPTy = dyn_cast<PointerType>(Ty)) + return PTy->getAddressSpace() == OtherPTy->getAddressSpace(); + return false; + } return false; // Other types have no identity values } @@ -155,7 +159,7 @@ int Type::getFPMantissaWidth() const { /// isSizedDerivedType - Derived types like structures and arrays are sized /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. -bool Type::isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited) const { +bool Type::isSizedDerivedType(SmallPtrSetImpl<const Type*> *Visited) const { if (const ArrayType *ATy = dyn_cast<ArrayType>(this)) return ATy->getElementType()->isSized(Visited); @@ -454,10 +458,11 @@ void StructType::setName(StringRef Name) { } // Look up the entry for the name. - EntryTy *Entry = &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name); - + auto IterBool = + getContext().pImpl->NamedStructTypes.insert(std::make_pair(Name, this)); + // While we have a name collision, try a random rename. - if (Entry->getValue()) { + if (!IterBool.second) { SmallString<64> TempStr(Name); TempStr.push_back('.'); raw_svector_ostream TmpStream(TempStr); @@ -467,19 +472,16 @@ void StructType::setName(StringRef Name) { TempStr.resize(NameSize + 1); TmpStream.resync(); TmpStream << getContext().pImpl->NamedStructTypesUniqueID++; - - Entry = &getContext().pImpl-> - NamedStructTypes.GetOrCreateValue(TmpStream.str()); - } while (Entry->getValue()); - } - // Okay, we found an entry that isn't used. It's us! - Entry->setValue(this); + IterBool = getContext().pImpl->NamedStructTypes.insert( + std::make_pair(TmpStream.str(), this)); + } while (!IterBool.second); + } // Delete the old string data. if (SymbolTableEntry) ((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator()); - SymbolTableEntry = Entry; + SymbolTableEntry = &*IterBool.first; } //===----------------------------------------------------------------------===// @@ -506,7 +508,9 @@ StructType *StructType::get(Type *type, ...) { StructFields.push_back(type); type = va_arg(ap, llvm::Type*); } - return llvm::StructType::get(Ctx, StructFields); + auto *Ret = llvm::StructType::get(Ctx, StructFields); + va_end(ap); + return Ret; } StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements, @@ -547,16 +551,18 @@ StructType *StructType::create(StringRef Name, Type *type, ...) { StructFields.push_back(type); type = va_arg(ap, llvm::Type*); } - return llvm::StructType::create(Ctx, StructFields, Name); + auto *Ret = llvm::StructType::create(Ctx, StructFields, Name); + va_end(ap); + return Ret; } -bool StructType::isSized(SmallPtrSet<const Type*, 4> *Visited) const { +bool StructType::isSized(SmallPtrSetImpl<const Type*> *Visited) const { if ((getSubclassData() & SCDB_IsSized) != 0) return true; if (isOpaque()) return false; - if (Visited && !Visited->insert(this)) + if (Visited && !Visited->insert(this).second) return false; // Okay, our struct is sized if all of the elements are, but if one of the @@ -591,6 +597,7 @@ void StructType::setBody(Type *type, ...) { type = va_arg(ap, llvm::Type*); } setBody(StructFields); + va_end(ap); } bool StructType::isValidElementType(Type *ElemTy) { diff --git a/lib/IR/TypeFinder.cpp b/lib/IR/TypeFinder.cpp index 689b903891..6796075bfc 100644 --- a/lib/IR/TypeFinder.cpp +++ b/lib/IR/TypeFinder.cpp @@ -40,7 +40,7 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { } // Get types from functions. - SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; + SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst; for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) { incorporateType(FI->getType()); diff --git a/lib/IR/Use.cpp b/lib/IR/Use.cpp index 047861c258..cae845d99f 100644 --- a/lib/IR/Use.cpp +++ b/lib/IR/Use.cpp @@ -52,7 +52,7 @@ unsigned Use::getOperandNo() const { // Sets up the waymarking algorithm's tags for a series of Uses. See the // algorithm details here: // -// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +// http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm // Use *Use::initTags(Use *const Start, Use *Stop) { ptrdiff_t Done = 0; diff --git a/lib/IR/UseListOrder.cpp b/lib/IR/UseListOrder.cpp new file mode 100644 index 0000000000..d064e67026 --- /dev/null +++ b/lib/IR/UseListOrder.cpp @@ -0,0 +1,43 @@ +//===- UseListOrder.cpp - Implement Use List Order ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implement structures and command-line options for preserving use-list order. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/UseListOrder.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +static cl::opt<bool> PreserveBitcodeUseListOrder( + "preserve-bc-use-list-order", + cl::desc("Experimental support to preserve bitcode use-list order."), + cl::init(false), cl::Hidden); + +static cl::opt<bool> PreserveAssemblyUseListOrder( + "preserve-ll-use-list-order", + cl::desc("Experimental support to preserve assembly use-list order."), + cl::init(false), cl::Hidden); + +bool llvm::shouldPreserveBitcodeUseListOrder() { + return PreserveBitcodeUseListOrder; +} + +bool llvm::shouldPreserveAssemblyUseListOrder() { + return PreserveAssemblyUseListOrder; +} + +void llvm::setPreserveBitcodeUseListOrder(bool ShouldPreserve) { + PreserveBitcodeUseListOrder = ShouldPreserve; +} + +void llvm::setPreserveAssemblyUseListOrder(bool ShouldPreserve) { + PreserveAssemblyUseListOrder = ShouldPreserve; +} diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp index 940682826a..ee83eacf2b 100644 --- a/lib/IR/User.cpp +++ b/lib/IR/User.cpp @@ -20,9 +20,6 @@ namespace llvm { void User::anchor() {} -// replaceUsesOfWith - Replaces all references to the "From" definition with -// references to the "To" definition. -// void User::replaceUsesOfWith(Value *From, Value *To) { if (From == To) return; // Duh what? diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 35c241a608..4e0c11f15f 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -15,6 +15,7 @@ #include "LLVMContextImpl.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -44,7 +45,8 @@ static inline Type *checkType(Type *Ty) { Value::Value(Type *ty, unsigned scid) : VTy(checkType(ty)), UseList(nullptr), Name(nullptr), SubclassID(scid), - HasValueHandle(0), SubclassOptionalData(0), SubclassData(0) { + HasValueHandle(0), SubclassOptionalData(0), SubclassData(0), + NumOperands(0) { // FIXME: Why isn't this in the subclass gunk?? // Note, we cannot call isa<CallInst> before the CallInst has been // constructed. @@ -87,8 +89,6 @@ Value::~Value() { LeakDetector::removeGarbageObject(this); } -/// hasNUses - Return true if this Value has exactly N users. -/// bool Value::hasNUses(unsigned N) const { const_use_iterator UI = use_begin(), E = use_end(); @@ -97,9 +97,6 @@ bool Value::hasNUses(unsigned N) const { return UI == E; } -/// hasNUsesOrMore - Return true if this value has N users or more. This is -/// logically equivalent to getNumUses() >= N. -/// bool Value::hasNUsesOrMore(unsigned N) const { const_use_iterator UI = use_begin(), E = use_end(); @@ -109,8 +106,6 @@ bool Value::hasNUsesOrMore(unsigned N) const { return true; } -/// isUsedInBasicBlock - Return true if this value is used in the specified -/// basic block. bool Value::isUsedInBasicBlock(const BasicBlock *BB) const { // This can be computed either by scanning the instructions in BB, or by // scanning the use list of this Value. Both lists can be very long, but @@ -132,10 +127,6 @@ bool Value::isUsedInBasicBlock(const BasicBlock *BB) const { return false; } - -/// getNumUses - This method computes the number of uses of this Value. This -/// is a linear time operation. Use hasOneUse or hasNUses to check for specific -/// values. unsigned Value::getNumUses() const { return (unsigned)std::distance(use_begin(), use_end()); } @@ -235,9 +226,6 @@ void Value::setName(const Twine &NewName) { Name = ST->createValueName(NameRef, this); } - -/// takeName - transfer the name from V to this value, setting V's name to -/// empty. It is an error to call V->takeName(V). void Value::takeName(Value *V) { assert(SubclassID != MDStringVal && "Cannot take the name of an MDString!"); @@ -302,9 +290,9 @@ void Value::takeName(Value *V) { } #ifndef NDEBUG -static bool contains(SmallPtrSet<ConstantExpr *, 4> &Cache, ConstantExpr *Expr, +static bool contains(SmallPtrSetImpl<ConstantExpr *> &Cache, ConstantExpr *Expr, Constant *C) { - if (!Cache.insert(Expr)) + if (!Cache.insert(Expr).second) return false; for (auto &O : Expr->operands()) { @@ -413,7 +401,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) { return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); - } while (Visited.insert(V)); + } while (Visited.insert(V).second); return V; } @@ -454,7 +442,8 @@ Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, return V; Offset = GEPOffset; V = GEP->getPointerOperand(); - } else if (Operator::getOpcode(V) == Instruction::BitCast) { + } else if (Operator::getOpcode(V) == Instruction::BitCast || + Operator::getOpcode(V) == Instruction::AddrSpaceCast) { V = cast<Operator>(V)->getOperand(0); } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { V = GA->getAliasee(); @@ -462,7 +451,7 @@ Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); - } while (Visited.insert(V)); + } while (Visited.insert(V).second); return V; } @@ -471,10 +460,12 @@ Value *Value::stripInBoundsOffsets() { return stripPointerCastsAndOffsets<PSK_InBounds>(this); } -/// isDereferenceablePointer - Test if this value is always a pointer to -/// allocated and suitably aligned memory for a simple load or store. +/// \brief Check if Value is always a dereferenceable pointer. +/// +/// Test if V is always a pointer to allocated and suitably aligned memory for +/// a simple load or store. static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, - SmallPtrSet<const Value *, 32> &Visited) { + SmallPtrSetImpl<const Value *> &Visited) { // Note that it is not safe to speculate into a malloc'd region because // malloc may return null. @@ -504,14 +495,34 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) return !GV->hasExternalWeakLinkage(); - // byval arguments are ok. - if (const Argument *A = dyn_cast<Argument>(V)) - return A->hasByValAttr(); + // byval arguments are okay. Arguments specifically marked as + // dereferenceable are okay too. + if (const Argument *A = dyn_cast<Argument>(V)) { + if (A->hasByValAttr()) + return true; + else if (uint64_t Bytes = A->getDereferenceableBytes()) { + Type *Ty = V->getType()->getPointerElementType(); + if (Ty->isSized() && DL && DL->getTypeStoreSize(Ty) <= Bytes) + return true; + } + + return false; + } + + // Return values from call sites specifically marked as dereferenceable are + // also okay. + if (ImmutableCallSite CS = V) { + if (uint64_t Bytes = CS.getDereferenceableBytes(0)) { + Type *Ty = V->getType()->getPointerElementType(); + if (Ty->isSized() && DL && DL->getTypeStoreSize(Ty) <= Bytes) + return true; + } + } // For GEPs, determine if the indexing lands within the allocated object. if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { // Conservatively require that the base pointer be fully dereferenceable. - if (!Visited.insert(GEP->getOperand(0))) + if (!Visited.insert(GEP->getOperand(0)).second) return false; if (!isDereferenceablePointer(GEP->getOperand(0), DL, Visited)) return false; @@ -543,21 +554,39 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, return true; } + if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(V)) + return isDereferenceablePointer(ASC->getOperand(0), DL, Visited); + // If we don't know, assume the worst. return false; } -/// isDereferenceablePointer - Test if this value is always a pointer to -/// allocated and suitably aligned memory for a simple load or store. bool Value::isDereferenceablePointer(const DataLayout *DL) const { + // When dereferenceability information is provided by a dereferenceable + // attribute, we know exactly how many bytes are dereferenceable. If we can + // determine the exact offset to the attributed variable, we can use that + // information here. + Type *Ty = getType()->getPointerElementType(); + if (Ty->isSized() && DL) { + APInt Offset(DL->getTypeStoreSizeInBits(getType()), 0); + const Value *BV = stripAndAccumulateInBoundsConstantOffsets(*DL, Offset); + + APInt DerefBytes(Offset.getBitWidth(), 0); + if (const Argument *A = dyn_cast<Argument>(BV)) + DerefBytes = A->getDereferenceableBytes(); + else if (ImmutableCallSite CS = BV) + DerefBytes = CS.getDereferenceableBytes(0); + + if (DerefBytes.getBoolValue() && Offset.isNonNegative()) { + if (DerefBytes.uge(Offset + DL->getTypeStoreSize(Ty))) + return true; + } + } + SmallPtrSet<const Value *, 32> Visited; return ::isDereferenceablePointer(this, DL, Visited); } -/// DoPHITranslation - If this value is a PHI node with CurBB as its parent, -/// return the value in the PHI node corresponding to PredBB. If not, return -/// ourself. This is useful if you want to know the value something has in a -/// predecessor block. Value *Value::DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) { PHINode *PN = dyn_cast<PHINode>(this); @@ -568,12 +597,29 @@ Value *Value::DoPHITranslation(const BasicBlock *CurBB, LLVMContext &Value::getContext() const { return VTy->getContext(); } +void Value::reverseUseList() { + if (!UseList || !UseList->Next) + // No need to reverse 0 or 1 uses. + return; + + Use *Head = UseList; + Use *Current = UseList->Next; + Head->Next = nullptr; + while (Current) { + Use *Next = Current->Next; + Current->Next = Head; + Head->setPrev(&Current->Next); + Head = Current; + Current = Next; + } + UseList = Head; + Head->setPrev(&UseList); +} + //===----------------------------------------------------------------------===// // ValueHandleBase Class //===----------------------------------------------------------------------===// -/// AddToExistingUseList - Add this ValueHandle to the use list for VP, where -/// List is known to point into the existing use list. void ValueHandleBase::AddToExistingUseList(ValueHandleBase **List) { assert(List && "Handle list is null?"); @@ -597,7 +643,6 @@ void ValueHandleBase::AddToExistingUseListAfter(ValueHandleBase *List) { Next->setPrevPtr(&Next); } -/// AddToUseList - Add this ValueHandle to the use list for VP. void ValueHandleBase::AddToUseList() { assert(VP.getPointer() && "Null pointer doesn't have a use list!"); @@ -641,7 +686,6 @@ void ValueHandleBase::AddToUseList() { } } -/// RemoveFromUseList - Remove this ValueHandle from its current use list. void ValueHandleBase::RemoveFromUseList() { assert(VP.getPointer() && VP.getPointer()->HasValueHandle && "Pointer doesn't have a use list!"); @@ -729,6 +773,8 @@ void ValueHandleBase::ValueIsDeleted(Value *V) { void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { assert(Old->HasValueHandle &&"Should only be called if ValueHandles present"); assert(Old != New && "Changing value into itself!"); + assert(Old->getType() == New->getType() && + "replaceAllUses of value with new value of different type!"); // Get the linked list base, which is guaranteed to exist since the // HasValueHandle flag is set. diff --git a/lib/IR/ValueSymbolTable.cpp b/lib/IR/ValueSymbolTable.cpp index e9e979a9a7..2b23f6dd15 100644 --- a/lib/IR/ValueSymbolTable.cpp +++ b/lib/IR/ValueSymbolTable.cpp @@ -56,11 +56,10 @@ void ValueSymbolTable::reinsertValue(Value* V) { raw_svector_ostream(UniqueName) << ++LastUnique; // Try insert the vmap entry with this suffix. - ValueName &NewName = vmap.GetOrCreateValue(UniqueName); - if (!NewName.getValue()) { + auto IterBool = vmap.insert(std::make_pair(UniqueName, V)); + if (IterBool.second) { // Newly inserted name. Success! - NewName.setValue(V); - V->Name = &NewName; + V->Name = &*IterBool.first; //DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n"); return; } @@ -78,12 +77,11 @@ void ValueSymbolTable::removeValueName(ValueName *V) { /// auto-renames the name and returns that instead. ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) { // In the common case, the name is not already in the symbol table. - ValueName &Entry = vmap.GetOrCreateValue(Name); - if (!Entry.getValue()) { - Entry.setValue(V); + auto IterBool = vmap.insert(std::make_pair(Name, V)); + if (IterBool.second) { //DEBUG(dbgs() << " Inserted value: " << Entry.getKeyData() << ": " // << *V << "\n"); - return &Entry; + return &*IterBool.first; } // Otherwise, there is a naming conflict. Rename this value. @@ -95,12 +93,11 @@ ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) { raw_svector_ostream(UniqueName) << ++LastUnique; // Try insert the vmap entry with this suffix. - ValueName &NewName = vmap.GetOrCreateValue(UniqueName); - if (!NewName.getValue()) { - // Newly inserted name. Success! - NewName.setValue(V); - //DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n"); - return &NewName; + auto IterBool = vmap.insert(std::make_pair(UniqueName, V)); + if (IterBool.second) { + // DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << + // "\n"); + return &*IterBool.first; } } } diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 314bad36b1..9698dbd77f 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -257,7 +257,7 @@ private: void visitGlobalVariable(const GlobalVariable &GV); void visitGlobalAlias(const GlobalAlias &GA); void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); - void visitAliaseeSubExpr(SmallPtrSet<const GlobalAlias *, 4> &Visited, + void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, const GlobalAlias &A, const Constant &C); void visitNamedMDNode(const NamedMDNode &NMD); void visitMDNode(MDNode &MD, Function *F); @@ -269,6 +269,8 @@ private: SmallVectorImpl<const MDNode *> &Requirements); void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); + void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty); + // InstVisitor overrides... using InstVisitor<Verifier>::visit; @@ -375,11 +377,13 @@ void Verifier::visit(Instruction &I) { void Verifier::visitGlobalValue(const GlobalValue &GV) { - Assert1(!GV.isDeclaration() || GV.isMaterializable() || - GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), + Assert1(!GV.isDeclaration() || GV.hasExternalLinkage() || + GV.hasExternalWeakLinkage(), "Global is external, but doesn't have external or weak linkage!", &GV); + Assert1(GV.getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &GV); Assert1(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV), "Only global variables can have appending linkage!", &GV); @@ -476,7 +480,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { while (!WorkStack.empty()) { const Value *V = WorkStack.pop_back_val(); - if (!Visited.insert(V)) + if (!Visited.insert(V).second) continue; if (const User *U = dyn_cast<User>(V)) { @@ -500,13 +504,13 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { visitAliaseeSubExpr(Visited, GA, C); } -void Verifier::visitAliaseeSubExpr(SmallPtrSet<const GlobalAlias *, 4> &Visited, +void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, const GlobalAlias &GA, const Constant &C) { if (const auto *GV = dyn_cast<GlobalValue>(&C)) { Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA); if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { - Assert1(Visited.insert(GA2), "Aliases cannot form a cycle", &GA); + Assert1(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA); Assert1(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias", &GA); @@ -564,7 +568,7 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { void Verifier::visitMDNode(MDNode &MD, Function *F) { // Only visit each node once. Metadata can be mutually recursive, so this // avoids infinite recursion here, as well as being an optimization. - if (!MDNodes.insert(&MD)) + if (!MDNodes.insert(&MD).second) return; for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) { @@ -605,11 +609,10 @@ void Verifier::visitComdat(const Comdat &C) { Assert1(GV, "comdat selection kind requires a global value with the same name", &C); - // The Module is invalid if the GlobalValue has local linkage. Allowing - // otherwise opens us up to seeing the underling global value get renamed if - // collisions occur. + // The Module is invalid if the GlobalValue has private linkage. Entities + // with private linkage don't have entries in the symbol table. if (GV) - Assert1(!GV->hasLocalLinkage(), "comdat global value has local linkage", + Assert1(!GV->hasPrivateLinkage(), "comdat global value has private linkage", GV); } @@ -672,24 +675,23 @@ Verifier::visitModuleFlag(const MDNode *Op, // constant int), the flag ID (an MDString), and the value. Assert1(Op->getNumOperands() == 3, "incorrect number of operands in module flag", Op); - ConstantInt *Behavior = dyn_cast<ConstantInt>(Op->getOperand(0)); + Module::ModFlagBehavior MFB; + if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { + Assert1( + dyn_cast<ConstantInt>(Op->getOperand(0)), + "invalid behavior operand in module flag (expected constant integer)", + Op->getOperand(0)); + Assert1(false, + "invalid behavior operand in module flag (unexpected constant)", + Op->getOperand(0)); + } MDString *ID = dyn_cast<MDString>(Op->getOperand(1)); - Assert1(Behavior, - "invalid behavior operand in module flag (expected constant integer)", - Op->getOperand(0)); - unsigned BehaviorValue = Behavior->getZExtValue(); Assert1(ID, "invalid ID operand in module flag (expected metadata string)", Op->getOperand(1)); // Sanity check the values for behaviors with additional requirements. - switch (BehaviorValue) { - default: - Assert1(false, - "invalid behavior operand in module flag (unexpected constant)", - Op->getOperand(0)); - break; - + switch (MFB) { case Module::Error: case Module::Warning: case Module::Override: @@ -725,7 +727,7 @@ Verifier::visitModuleFlag(const MDNode *Op, } // Unless this is a "requires" flag, check the ID is unique. - if (BehaviorValue != Module::Require) { + if (MFB != Module::Require) { bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; Assert1(Inserted, "module flag identifiers must be unique (or of 'require' type)", @@ -1054,20 +1056,19 @@ void Verifier::visitFunction(const Function &F) { "Attribute 'builtin' can only be applied to a callsite.", &F); // Check that this function meets the restrictions on this calling convention. + // Sometimes varargs is used for perfectly forwarding thunks, so some of these + // restrictions can be lifted. switch (F.getCallingConv()) { default: - break; case CallingConv::C: break; case CallingConv::Fast: case CallingConv::Cold: - case CallingConv::X86_FastCall: - case CallingConv::X86_ThisCall: case CallingConv::Intel_OCL_BI: case CallingConv::PTX_Kernel: case CallingConv::PTX_Device: - Assert1(!F.isVarArg(), - "Varargs functions must have C calling conventions!", &F); + Assert1(!F.isVarArg(), "Calling convention does not support varargs or " + "perfect forwarding!", &F); break; } @@ -1175,6 +1176,12 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { } } } + + // Check that all instructions have their parent pointers set up correctly. + for (auto &I : BB) + { + Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!"); + } } void Verifier::visitTerminatorInst(TerminatorInst &I) { @@ -1217,7 +1224,7 @@ void Verifier::visitSwitchInst(SwitchInst &SI) { for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { Assert1(i.getCaseValue()->getType() == SwitchTy, "Switch constants must all be same type as switch value!", &SI); - Assert2(Constants.insert(i.getCaseValue()), + Assert2(Constants.insert(i.getCaseValue()).second, "Duplicate integer as switch case", &SI, i.getCaseValue()); } @@ -1886,12 +1893,63 @@ static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); } +void Verifier::visitRangeMetadata(Instruction& I, + MDNode* Range, Type* Ty) { + assert(Range && + Range == I.getMetadata(LLVMContext::MD_range) && + "precondition violation"); + + unsigned NumOperands = Range->getNumOperands(); + Assert1(NumOperands % 2 == 0, "Unfinished range!", Range); + unsigned NumRanges = NumOperands / 2; + Assert1(NumRanges >= 1, "It should have at least one range!", Range); + + ConstantRange LastRange(1); // Dummy initial value + for (unsigned i = 0; i < NumRanges; ++i) { + ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i)); + Assert1(Low, "The lower limit must be an integer!", Low); + ConstantInt *High = dyn_cast<ConstantInt>(Range->getOperand(2*i + 1)); + Assert1(High, "The upper limit must be an integer!", High); + Assert1(High->getType() == Low->getType() && + High->getType() == Ty, "Range types must match instruction type!", + &I); + + APInt HighV = High->getValue(); + APInt LowV = Low->getValue(); + ConstantRange CurRange(LowV, HighV); + Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(), + "Range must not be empty!", Range); + if (i != 0) { + Assert1(CurRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order", + Range); + Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous", + Range); + } + LastRange = ConstantRange(LowV, HighV); + } + if (NumRanges > 2) { + APInt FirstLow = + dyn_cast<ConstantInt>(Range->getOperand(0))->getValue(); + APInt FirstHigh = + dyn_cast<ConstantInt>(Range->getOperand(1))->getValue(); + ConstantRange FirstRange(FirstLow, FirstHigh); + Assert1(FirstRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous", + Range); + } +} + void Verifier::visitLoadInst(LoadInst &LI) { PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); Assert1(PTy, "Load operand must be a pointer.", &LI); Type *ElTy = PTy->getElementType(); Assert2(ElTy == LI.getType(), "Load result type does not match pointer operand type!", &LI, ElTy); + Assert1(LI.getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &LI); if (LI.isAtomic()) { Assert1(LI.getOrdering() != Release && LI.getOrdering() != AcquireRelease, "Load cannot have Release ordering", &LI); @@ -1911,52 +1969,6 @@ void Verifier::visitLoadInst(LoadInst &LI) { "Non-atomic load cannot have SynchronizationScope specified", &LI); } - if (MDNode *Range = LI.getMetadata(LLVMContext::MD_range)) { - unsigned NumOperands = Range->getNumOperands(); - Assert1(NumOperands % 2 == 0, "Unfinished range!", Range); - unsigned NumRanges = NumOperands / 2; - Assert1(NumRanges >= 1, "It should have at least one range!", Range); - - ConstantRange LastRange(1); // Dummy initial value - for (unsigned i = 0; i < NumRanges; ++i) { - ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i)); - Assert1(Low, "The lower limit must be an integer!", Low); - ConstantInt *High = dyn_cast<ConstantInt>(Range->getOperand(2*i + 1)); - Assert1(High, "The upper limit must be an integer!", High); - Assert1(High->getType() == Low->getType() && - High->getType() == ElTy, "Range types must match load type!", - &LI); - - APInt HighV = High->getValue(); - APInt LowV = Low->getValue(); - ConstantRange CurRange(LowV, HighV); - Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(), - "Range must not be empty!", Range); - if (i != 0) { - Assert1(CurRange.intersectWith(LastRange).isEmptySet(), - "Intervals are overlapping", Range); - Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order", - Range); - Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous", - Range); - } - LastRange = ConstantRange(LowV, HighV); - } - if (NumRanges > 2) { - APInt FirstLow = - dyn_cast<ConstantInt>(Range->getOperand(0))->getValue(); - APInt FirstHigh = - dyn_cast<ConstantInt>(Range->getOperand(1))->getValue(); - ConstantRange FirstRange(FirstLow, FirstHigh); - Assert1(FirstRange.intersectWith(LastRange).isEmptySet(), - "Intervals are overlapping", Range); - Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous", - Range); - } - - - } - visitInstruction(LI); } @@ -1967,6 +1979,8 @@ void Verifier::visitStoreInst(StoreInst &SI) { Assert2(ElTy == SI.getOperand(0)->getType(), "Stored value type does not match pointer operand type!", &SI, ElTy); + Assert1(SI.getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &SI); if (SI.isAtomic()) { Assert1(SI.getOrdering() != Acquire && SI.getOrdering() != AcquireRelease, "Store cannot have Acquire ordering", &SI); @@ -1998,6 +2012,8 @@ void Verifier::visitAllocaInst(AllocaInst &AI) { &AI); Assert1(AI.getArraySize()->getType()->isIntegerTy(), "Alloca array size must have integer type", &AI); + Assert1(AI.getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &AI); visitInstruction(AI); } @@ -2207,11 +2223,15 @@ void Verifier::visitInstruction(Instruction &I) { if (Function *F = dyn_cast<Function>(I.getOperand(i))) { // Check to make sure that the "address of" an intrinsic function is never // taken. - Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 : 0), + Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 : + isa<InvokeInst>(I) ? e-3 : 0), "Cannot take the address of an intrinsic!", &I); Assert1(!F->isIntrinsic() || isa<CallInst>(I) || - F->getIntrinsicID() == Intrinsic::donothing, - "Cannot invoke an intrinsinc other than donothing", &I); + F->getIntrinsicID() == Intrinsic::donothing || + F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || + F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64, + "Cannot invoke an intrinsinc other than" + " donothing or patchpoint", &I); Assert1(F->getParent() == M, "Referencing function in another module!", &I); } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { @@ -2239,7 +2259,7 @@ void Verifier::visitInstruction(Instruction &I) { while (!Stack.empty()) { const ConstantExpr *V = Stack.pop_back_val(); - if (!Visited.insert(V)) + if (!Visited.insert(V).second) continue; VerifyConstantExprBitcastType(V); @@ -2267,9 +2287,19 @@ void Verifier::visitInstruction(Instruction &I) { } } - MDNode *MD = I.getMetadata(LLVMContext::MD_range); - Assert1(!MD || isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I), - "Ranges are only for loads, calls and invokes!", &I); + if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { + Assert1(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I), + "Ranges are only for loads, calls and invokes!", &I); + visitRangeMetadata(I, Range, I.getType()); + } + + if (I.getMetadata(LLVMContext::MD_nonnull)) { + Assert1(I.getType()->isPointerTy(), + "nonnull applies only to pointer types", &I); + Assert1(isa<LoadInst>(I), + "nonnull applies only to load instructions, use attributes" + " for calls or invokes", &I); + } InstsInThisBlock.insert(&I); } @@ -2608,7 +2638,7 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS) { bool Broken = false; for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration()) + if (!I->isDeclaration() && !I->isMaterializable()) Broken |= !V.verify(*I); // Note that this function's return value is inverted from what you would |