diff options
Diffstat (limited to 'contrib/llvm/lib/IR')
52 files changed, 7078 insertions, 5706 deletions
diff --git a/contrib/llvm/lib/IR/AsmWriter.cpp b/contrib/llvm/lib/IR/AsmWriter.cpp index c494d6c..bc35cb3 100644 --- a/contrib/llvm/lib/IR/AsmWriter.cpp +++ b/contrib/llvm/lib/IR/AsmWriter.cpp @@ -14,9 +14,9 @@ // //===----------------------------------------------------------------------===// -#include "AsmWriter.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/AssemblyAnnotationWriter.h" @@ -31,13 +31,16 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/Statepoint.h" #include "llvm/IR/TypeFinder.h" +#include "llvm/IR/UseListOrder.h" #include "llvm/IR/ValueSymbolTable.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cctype> using namespace llvm; @@ -64,7 +67,7 @@ struct OrderMap { IDs[V].first = ID; } }; -} +} // namespace static void orderValue(const Value *V, OrderMap &OM) { if (OM.lookup(V).first) @@ -106,6 +109,10 @@ static OrderMap orderModule(const Module *M) { if (!isa<GlobalValue>(F.getPrologueData())) orderValue(F.getPrologueData(), OM); + if (F.hasPersonalityFn()) + if (!isa<GlobalValue>(F.getPersonalityFn())) + orderValue(F.getPersonalityFn(), OM); + orderValue(&F, OM); if (F.isDeclaration()) @@ -275,6 +282,15 @@ static const Module *getModuleFromVal(const Value *V) { if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) return GV->getParent(); + + if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) { + for (const User *U : MAV->users()) + if (isa<Instruction>(U)) + if (const Module *M = getModuleFromVal(U)) + return M; + return nullptr; + } + return nullptr; } @@ -378,7 +394,27 @@ static void PrintLLVMName(raw_ostream &OS, const Value *V) { } -namespace llvm { +namespace { +class TypePrinting { + TypePrinting(const TypePrinting &) = delete; + void operator=(const TypePrinting&) = delete; +public: + + /// NamedTypes - The named types that are used by the current module. + TypeFinder NamedTypes; + + /// NumberedTypes - The numbered types, along with their value. + DenseMap<StructType*, unsigned> NumberedTypes; + + TypePrinting() = default; + + void incorporateTypes(const Module &M); + + void print(Type *Ty, raw_ostream &OS); + + void printStructBody(StructType *Ty, raw_ostream &OS); +}; +} // namespace void TypePrinting::incorporateTypes(const Module &M) { NamedTypes.run(M, false); @@ -508,6 +544,7 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) { OS << '>'; } +namespace { //===----------------------------------------------------------------------===// // SlotTracker Class: Enumerate slot numbers for unnamed values //===----------------------------------------------------------------------===// @@ -525,6 +562,7 @@ private: /// TheFunction - The function for which we are holding slot numbers. const Function* TheFunction; bool FunctionProcessed; + bool ShouldInitializeAllMetadata; /// mMap - The slot map for the module level data. ValueMap mMap; @@ -542,10 +580,20 @@ private: DenseMap<AttributeSet, unsigned> asMap; unsigned asNext; public: - /// Construct from a module - explicit SlotTracker(const Module *M); + /// Construct from a module. + /// + /// If \c ShouldInitializeAllMetadata, initializes all metadata in all + /// functions, giving correct numbering for metadata referenced only from + /// within a function (even if no functions have been initialized). + explicit SlotTracker(const Module *M, + bool ShouldInitializeAllMetadata = false); /// Construct from a function, starting out in incorp state. - explicit SlotTracker(const Function *F); + /// + /// If \c ShouldInitializeAllMetadata, initializes all metadata in all + /// functions, giving correct numbering for metadata referenced only from + /// within a function (even if no functions have been initialized). + explicit SlotTracker(const Function *F, + bool ShouldInitializeAllMetadata = false); /// Return the slot number of the specified value in it's type /// plane. If something is not in the SlotTracker, return -1. @@ -606,11 +654,18 @@ private: /// Add all of the functions arguments, basic blocks, and instructions. void processFunction(); - SlotTracker(const SlotTracker &) LLVM_DELETED_FUNCTION; - void operator=(const SlotTracker &) LLVM_DELETED_FUNCTION; + /// Add all of the metadata from a function. + void processFunctionMetadata(const Function &F); + + /// Add all of the metadata from an instruction. + void processInstructionMetadata(const Instruction &I); + + SlotTracker(const SlotTracker &) = delete; + void operator=(const SlotTracker &) = delete; }; +} // namespace -SlotTracker *createSlotTracker(const Module *M) { +static SlotTracker *createSlotTracker(const Module *M) { return new SlotTracker(M); } @@ -645,15 +700,18 @@ static SlotTracker *createSlotTracker(const Value *V) { // Module level constructor. Causes the contents of the Module (sans functions) // to be added to the slot table. -SlotTracker::SlotTracker(const Module *M) - : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), mNext(0), +SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata) + : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), + ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), fNext(0), mdnNext(0), asNext(0) {} // Function level constructor. Causes the contents of the Module and the one // function provided to be added to the slot table. -SlotTracker::SlotTracker(const Function *F) +SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata) : TheModule(F ? F->getParent() : nullptr), TheFunction(F), - FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {} + FunctionProcessed(false), + ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0), + fNext(0), mdnNext(0), asNext(0) {} inline void SlotTracker::initialize() { if (TheModule) { @@ -671,30 +729,33 @@ void SlotTracker::processModule() { ST_DEBUG("begin processModule!\n"); // Add all of the unnamed global variables to the value table. - for (Module::const_global_iterator I = TheModule->global_begin(), - E = TheModule->global_end(); I != E; ++I) { - if (!I->hasName()) - CreateModuleSlot(I); + for (const GlobalVariable &Var : TheModule->globals()) { + if (!Var.hasName()) + CreateModuleSlot(&Var); + } + + for (const GlobalAlias &A : TheModule->aliases()) { + if (!A.hasName()) + CreateModuleSlot(&A); } // Add metadata used by named metadata. - for (Module::const_named_metadata_iterator - I = TheModule->named_metadata_begin(), - E = TheModule->named_metadata_end(); I != E; ++I) { - const NamedMDNode *NMD = I; - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - CreateMetadataSlot(NMD->getOperand(i)); + for (const NamedMDNode &NMD : TheModule->named_metadata()) { + for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) + CreateMetadataSlot(NMD.getOperand(i)); } - for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); - I != E; ++I) { - if (!I->hasName()) + for (const Function &F : *TheModule) { + if (!F.hasName()) // Add all the unnamed functions to the table. - CreateModuleSlot(I); + CreateModuleSlot(&F); + + if (ShouldInitializeAllMetadata) + processFunctionMetadata(F); // Add all the function attributes to the table. // FIXME: Add attributes of other objects? - AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); + AttributeSet FnAttrs = F.getAttributes().getFnAttributes(); if (FnAttrs.hasAttributes(AttributeSet::FunctionIndex)) CreateAttributeSetSlot(FnAttrs); } @@ -715,46 +776,30 @@ void SlotTracker::processFunction() { ST_DEBUG("Inserting Instructions:\n"); - 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(), - E = TheFunction->end(); BB != E; ++BB) { - if (!BB->hasName()) - CreateFunctionSlot(BB); - - for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; - ++I) { - if (!I->getType()->isVoidTy() && !I->hasName()) - CreateFunctionSlot(I); - - // Intrinsics can directly use metadata. We allow direct calls to any - // llvm.foo function here, because the target may not be linked into the - // optimizer. - if (const CallInst *CI = dyn_cast<CallInst>(I)) { - if (Function *F = CI->getCalledFunction()) - if (F->isIntrinsic()) - for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) - if (auto *V = dyn_cast_or_null<MetadataAsValue>(I->getOperand(i))) - if (MDNode *N = dyn_cast<MDNode>(V->getMetadata())) - CreateMetadataSlot(N); + for (auto &BB : *TheFunction) { + if (!BB.hasName()) + CreateFunctionSlot(&BB); + processFunctionMetadata(*TheFunction); + + for (auto &I : BB) { + if (!I.getType()->isVoidTy() && !I.hasName()) + CreateFunctionSlot(&I); + + // We allow direct calls to any llvm.foo function here, because the + // target may not be linked into the optimizer. + if (const CallInst *CI = dyn_cast<CallInst>(&I)) { // Add all the call attributes to the table. AttributeSet Attrs = CI->getAttributes().getFnAttributes(); if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) CreateAttributeSetSlot(Attrs); - } else if (const InvokeInst *II = dyn_cast<InvokeInst>(I)) { + } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) { // Add all the call attributes to the table. AttributeSet Attrs = II->getAttributes().getFnAttributes(); if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) CreateAttributeSetSlot(Attrs); } - - // Process metadata attached with this instruction. - I->getAllMetadata(MDForInst); - for (unsigned i = 0, e = MDForInst.size(); i != e; ++i) - CreateMetadataSlot(MDForInst[i].second); - MDForInst.clear(); } } @@ -763,6 +808,35 @@ void SlotTracker::processFunction() { ST_DEBUG("end processFunction!\n"); } +void SlotTracker::processFunctionMetadata(const Function &F) { + SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; + for (auto &BB : F) { + F.getAllMetadata(MDs); + for (auto &MD : MDs) + CreateMetadataSlot(MD.second); + + for (auto &I : BB) + processInstructionMetadata(I); + } +} + +void SlotTracker::processInstructionMetadata(const Instruction &I) { + // Process metadata used directly by intrinsics. + if (const CallInst *CI = dyn_cast<CallInst>(&I)) + if (Function *F = CI->getCalledFunction()) + if (F->isIntrinsic()) + for (auto &Op : I.operands()) + if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op)) + if (MDNode *N = dyn_cast<MDNode>(V->getMetadata())) + CreateMetadataSlot(N); + + // Process metadata attached to this instruction. + SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; + I.getAllMetadata(MDs); + for (auto &MD : MDs) + CreateMetadataSlot(MD.second); +} + /// Clean up after incorporating a function. This is the only way to get out of /// the function incorporation state that affects get*Slot/Create*Slot. Function /// incorporation state is indicated by TheFunction != 0. @@ -1010,7 +1084,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, (StrVal[1] >= '0' && StrVal[1] <= '9'))) { // Reparse stringized version! if (APFloat(APFloat::IEEEdouble, StrVal).convertToDouble() == Val) { - Out << StrVal.str(); + Out << StrVal; return; } } @@ -1223,6 +1297,14 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << ' ' << getPredicateText(CE->getPredicate()); Out << " ("; + if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) { + TypePrinter.print( + cast<PointerType>(GEP->getPointerOperandType()->getScalarType()) + ->getElementType(), + Out); + Out << ", "; + } + for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) { TypePrinter.print((*OI)->getType(), Out); Out << ' '; @@ -1275,52 +1357,474 @@ static void writeMDTuple(raw_ostream &Out, const MDTuple *Node, namespace { struct FieldSeparator { bool Skip; - FieldSeparator() : Skip(true) {} + const char *Sep; + FieldSeparator(const char *Sep = ", ") : Skip(true), Sep(Sep) {} }; raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) { if (FS.Skip) { FS.Skip = false; return OS; } - return OS << ", "; + return OS << FS.Sep; } +struct MDFieldPrinter { + raw_ostream &Out; + FieldSeparator FS; + TypePrinting *TypePrinter; + SlotTracker *Machine; + const Module *Context; + + explicit MDFieldPrinter(raw_ostream &Out) + : Out(Out), TypePrinter(nullptr), Machine(nullptr), Context(nullptr) {} + MDFieldPrinter(raw_ostream &Out, TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) + : Out(Out), TypePrinter(TypePrinter), Machine(Machine), Context(Context) { + } + void printTag(const DINode *N); + void printString(StringRef Name, StringRef Value, + bool ShouldSkipEmpty = true); + void printMetadata(StringRef Name, const Metadata *MD, + bool ShouldSkipNull = true); + template <class IntTy> + void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true); + void printBool(StringRef Name, bool Value); + void printDIFlags(StringRef Name, unsigned Flags); + template <class IntTy, class Stringifier> + void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString, + bool ShouldSkipZero = true); +}; } // end namespace -static void writeMDLocation(raw_ostream &Out, const MDLocation *DL, +void MDFieldPrinter::printTag(const DINode *N) { + Out << FS << "tag: "; + if (const char *Tag = dwarf::TagString(N->getTag())) + Out << Tag; + else + Out << N->getTag(); +} + +void MDFieldPrinter::printString(StringRef Name, StringRef Value, + bool ShouldSkipEmpty) { + if (ShouldSkipEmpty && Value.empty()) + return; + + Out << FS << Name << ": \""; + PrintEscapedString(Value, Out); + Out << "\""; +} + +static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + if (!MD) { + Out << "null"; + return; + } + WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context); +} + +void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD, + bool ShouldSkipNull) { + if (ShouldSkipNull && !MD) + return; + + Out << FS << Name << ": "; + writeMetadataAsOperand(Out, MD, TypePrinter, Machine, Context); +} + +template <class IntTy> +void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) { + if (ShouldSkipZero && !Int) + return; + + Out << FS << Name << ": " << Int; +} + +void MDFieldPrinter::printBool(StringRef Name, bool Value) { + Out << FS << Name << ": " << (Value ? "true" : "false"); +} + +void MDFieldPrinter::printDIFlags(StringRef Name, unsigned Flags) { + if (!Flags) + return; + + Out << FS << Name << ": "; + + SmallVector<unsigned, 8> SplitFlags; + unsigned Extra = DINode::splitFlags(Flags, SplitFlags); + + FieldSeparator FlagsFS(" | "); + for (unsigned F : SplitFlags) { + const char *StringF = DINode::getFlagString(F); + assert(StringF && "Expected valid flag"); + Out << FlagsFS << StringF; + } + if (Extra || SplitFlags.empty()) + Out << FlagsFS << Extra; +} + +template <class IntTy, class Stringifier> +void MDFieldPrinter::printDwarfEnum(StringRef Name, IntTy Value, + Stringifier toString, bool ShouldSkipZero) { + if (!Value) + return; + + Out << FS << Name << ": "; + if (const char *S = toString(Value)) + Out << S; + else + Out << Value; +} + +static void writeGenericDINode(raw_ostream &Out, const GenericDINode *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!GenericDINode("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("header", N->getHeader()); + if (N->getNumDwarfOperands()) { + Out << Printer.FS << "operands: {"; + FieldSeparator IFS; + for (auto &I : N->dwarf_operands()) { + Out << IFS; + writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context); + } + Out << "}"; + } + Out << ")"; +} + +static void writeDILocation(raw_ostream &Out, const DILocation *DL, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { - Out << "!MDLocation("; - FieldSeparator FS; + Out << "!DILocation("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); // Always output the line, since 0 is a relevant and important value for it. - Out << FS << "line: " << DL->getLine(); - if (DL->getColumn()) - Out << FS << "column: " << DL->getColumn(); - Out << FS << "scope: "; - WriteAsOperandInternal(Out, DL->getScope(), TypePrinter, Machine, Context); - if (DL->getInlinedAt()) { - Out << FS << "inlinedAt: "; - WriteAsOperandInternal(Out, DL->getInlinedAt(), TypePrinter, Machine, - Context); + Printer.printInt("line", DL->getLine(), /* ShouldSkipZero */ false); + Printer.printInt("column", DL->getColumn()); + Printer.printMetadata("scope", DL->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("inlinedAt", DL->getRawInlinedAt()); + Out << ")"; +} + +static void writeDISubrange(raw_ostream &Out, const DISubrange *N, + TypePrinting *, SlotTracker *, const Module *) { + Out << "!DISubrange("; + MDFieldPrinter Printer(Out); + Printer.printInt("count", N->getCount(), /* ShouldSkipZero */ false); + Printer.printInt("lowerBound", N->getLowerBound()); + Out << ")"; +} + +static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N, + TypePrinting *, SlotTracker *, const Module *) { + Out << "!DIEnumerator("; + MDFieldPrinter Printer(Out); + Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false); + Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false); + Out << ")"; +} + +static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N, + TypePrinting *, SlotTracker *, const Module *) { + Out << "!DIBasicType("; + MDFieldPrinter Printer(Out); + if (N->getTag() != dwarf::DW_TAG_base_type) + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printInt("size", N->getSizeInBits()); + Printer.printInt("align", N->getAlignInBits()); + Printer.printDwarfEnum("encoding", N->getEncoding(), + dwarf::AttributeEncodingString); + Out << ")"; +} + +static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DIDerivedType("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getRawScope()); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("baseType", N->getRawBaseType(), + /* ShouldSkipNull */ false); + Printer.printInt("size", N->getSizeInBits()); + Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("offset", N->getOffsetInBits()); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("extraData", N->getRawExtraData()); + Out << ")"; +} + +static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DICompositeType("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getRawScope()); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("baseType", N->getRawBaseType()); + Printer.printInt("size", N->getSizeInBits()); + Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("offset", N->getOffsetInBits()); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("elements", N->getRawElements()); + Printer.printDwarfEnum("runtimeLang", N->getRuntimeLang(), + dwarf::LanguageString); + Printer.printMetadata("vtableHolder", N->getRawVTableHolder()); + Printer.printMetadata("templateParams", N->getRawTemplateParams()); + Printer.printString("identifier", N->getIdentifier()); + Out << ")"; +} + +static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DISubroutineType("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("types", N->getRawTypeArray(), + /* ShouldSkipNull */ false); + Out << ")"; +} + +static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *, + SlotTracker *, const Module *) { + Out << "!DIFile("; + MDFieldPrinter Printer(Out); + Printer.printString("filename", N->getFilename(), + /* ShouldSkipEmpty */ false); + Printer.printString("directory", N->getDirectory(), + /* ShouldSkipEmpty */ false); + Out << ")"; +} + +static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DICompileUnit("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printDwarfEnum("language", N->getSourceLanguage(), + dwarf::LanguageString, /* ShouldSkipZero */ false); + Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false); + Printer.printString("producer", N->getProducer()); + Printer.printBool("isOptimized", N->isOptimized()); + Printer.printString("flags", N->getFlags()); + Printer.printInt("runtimeVersion", N->getRuntimeVersion(), + /* ShouldSkipZero */ false); + Printer.printString("splitDebugFilename", N->getSplitDebugFilename()); + Printer.printInt("emissionKind", N->getEmissionKind(), + /* ShouldSkipZero */ false); + Printer.printMetadata("enums", N->getRawEnumTypes()); + Printer.printMetadata("retainedTypes", N->getRawRetainedTypes()); + Printer.printMetadata("subprograms", N->getRawSubprograms()); + Printer.printMetadata("globals", N->getRawGlobalVariables()); + Printer.printMetadata("imports", N->getRawImportedEntities()); + Printer.printInt("dwoId", N->getDWOId()); + Out << ")"; +} + +static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DISubprogram("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printString("linkageName", N->getLinkageName()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("type", N->getRawType()); + Printer.printBool("isLocal", N->isLocalToUnit()); + Printer.printBool("isDefinition", N->isDefinition()); + Printer.printInt("scopeLine", N->getScopeLine()); + Printer.printMetadata("containingType", N->getRawContainingType()); + Printer.printDwarfEnum("virtuality", N->getVirtuality(), + dwarf::VirtualityString); + Printer.printInt("virtualIndex", N->getVirtualIndex()); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printBool("isOptimized", N->isOptimized()); + Printer.printMetadata("function", N->getRawFunction()); + Printer.printMetadata("templateParams", N->getRawTemplateParams()); + Printer.printMetadata("declaration", N->getRawDeclaration()); + Printer.printMetadata("variables", N->getRawVariables()); + Out << ")"; +} + +static void writeDILexicalBlock(raw_ostream &Out, const DILexicalBlock *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DILexicalBlock("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printInt("column", N->getColumn()); + Out << ")"; +} + +static void writeDILexicalBlockFile(raw_ostream &Out, + const DILexicalBlockFile *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!DILexicalBlockFile("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("discriminator", N->getDiscriminator(), + /* ShouldSkipZero */ false); + Out << ")"; +} + +static void writeDINamespace(raw_ostream &Out, const DINamespace *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DINamespace("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Out << ")"; +} + +static void writeDITemplateTypeParameter(raw_ostream &Out, + const DITemplateTypeParameter *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!DITemplateTypeParameter("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false); + Out << ")"; +} + +static void writeDITemplateValueParameter(raw_ostream &Out, + const DITemplateValueParameter *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!DITemplateValueParameter("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + if (N->getTag() != dwarf::DW_TAG_template_value_parameter) + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("type", N->getRawType()); + Printer.printMetadata("value", N->getValue(), /* ShouldSkipNull */ false); + Out << ")"; +} + +static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DIGlobalVariable("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printString("linkageName", N->getLinkageName()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("type", N->getRawType()); + Printer.printBool("isLocal", N->isLocalToUnit()); + Printer.printBool("isDefinition", N->isDefinition()); + Printer.printMetadata("variable", N->getRawVariable()); + Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); + Out << ")"; +} + +static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DILocalVariable("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printInt("arg", N->getArg(), + /* ShouldSkipZero */ + N->getTag() == dwarf::DW_TAG_auto_variable); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("type", N->getRawType()); + Printer.printDIFlags("flags", N->getFlags()); + Out << ")"; +} + +static void writeDIExpression(raw_ostream &Out, const DIExpression *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DIExpression("; + FieldSeparator FS; + if (N->isValid()) { + for (auto I = N->expr_op_begin(), E = N->expr_op_end(); I != E; ++I) { + const char *OpStr = dwarf::OperationEncodingString(I->getOp()); + assert(OpStr && "Expected valid opcode"); + + Out << FS << OpStr; + for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A) + Out << FS << I->getArg(A); + } + } else { + for (const auto &I : N->getElements()) + Out << FS << I; } Out << ")"; } +static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DIObjCProperty("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("file", N->getRawFile()); + Printer.printInt("line", N->getLine()); + Printer.printString("setter", N->getSetterName()); + Printer.printString("getter", N->getGetterName()); + Printer.printInt("attributes", N->getAttributes()); + Printer.printMetadata("type", N->getRawType()); + Out << ")"; +} + +static void writeDIImportedEntity(raw_ostream &Out, const DIImportedEntity *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!DIImportedEntity("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("entity", N->getRawEntity()); + Printer.printInt("line", N->getLine()); + Out << ")"; +} + + static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { - assert(isa<UniquableMDNode>(Node) && "Expected uniquable MDNode"); - - auto *Uniquable = cast<UniquableMDNode>(Node); - if (Uniquable->isDistinct()) + if (Node->isDistinct()) Out << "distinct "; + else if (Node->isTemporary()) + Out << "<temporary!> "; // Handle broken code. - switch (Uniquable->getMetadataID()) { + switch (Node->getMetadataID()) { default: llvm_unreachable("Expected uniquable MDNode"); -#define HANDLE_UNIQUABLE_LEAF(CLASS) \ +#define HANDLE_MDNODE_LEAF(CLASS) \ case Metadata::CLASS##Kind: \ - write##CLASS(Out, cast<CLASS>(Uniquable), TypePrinter, Machine, Context); \ + write##CLASS(Out, cast<CLASS>(Node), TypePrinter, Machine, Context); \ break; #include "llvm/IR/Metadata.def" } @@ -1440,6 +1944,77 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context); } +namespace { +class AssemblyWriter { + formatted_raw_ostream &Out; + const Module *TheModule; + std::unique_ptr<SlotTracker> ModuleSlotTracker; + SlotTracker &Machine; + TypePrinting TypePrinter; + AssemblyAnnotationWriter *AnnotationWriter; + SetVector<const Comdat *> Comdats; + bool ShouldPreserveUseListOrder; + UseListOrderStack UseListOrders; + SmallVector<StringRef, 8> MDNames; + +public: + /// Construct an AssemblyWriter with an external SlotTracker + AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, const Module *M, + AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false); + + /// Construct an AssemblyWriter with an internally allocated SlotTracker + AssemblyWriter(formatted_raw_ostream &o, const Module *M, + AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false); + + void printMDNodeBody(const MDNode *MD); + void printNamedMDNode(const NamedMDNode *NMD); + + void printModule(const Module *M); + + void writeOperand(const Value *Op, bool PrintType); + void writeParamOperand(const Value *Operand, AttributeSet Attrs,unsigned Idx); + void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope); + void writeAtomicCmpXchg(AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope); + + void writeAllMDNodes(); + void writeMDNode(unsigned Slot, const MDNode *Node); + void writeAllAttributeGroups(); + + void printTypeIdentities(); + void printGlobal(const GlobalVariable *GV); + void printAlias(const GlobalAlias *GV); + void printComdat(const Comdat *C); + void printFunction(const Function *F); + void printArgument(const Argument *FA, AttributeSet Attrs, unsigned Idx); + void printBasicBlock(const BasicBlock *BB); + void printInstructionLine(const Instruction &I); + void printInstruction(const Instruction &I); + + void printUseListOrder(const UseListOrder &Order); + void printUseLists(const Function *F); + +private: + void init(); + + /// \brief Print out metadata attachments. + void printMetadataAttachments( + const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs, + StringRef Separator); + + // printInfoComment - Print a little comment after the instruction indicating + // which slot it occupies. + void printInfoComment(const Value &V); + + // printGCRelocateComment - print comment after call to the gc.relocate + // intrinsic indicating base and derived pointer names. + void printGCRelocateComment(const Value &V); +}; +} // namespace + void AssemblyWriter::init() { if (!TheModule) return; @@ -1452,23 +2027,23 @@ void AssemblyWriter::init() { Comdats.insert(C); } - AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, - const Module *M, - AssemblyAnnotationWriter *AAW) - : Out(o), TheModule(M), Machine(Mac), AnnotationWriter(AAW) { + const Module *M, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder) + : Out(o), TheModule(M), Machine(Mac), AnnotationWriter(AAW), + ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) { init(); } AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, const Module *M, - AssemblyAnnotationWriter *AAW) - : Out(o), TheModule(M), ModuleSlotTracker(createSlotTracker(M)), - Machine(*ModuleSlotTracker), AnnotationWriter(AAW) { + AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder) + : Out(o), TheModule(M), ModuleSlotTracker(createSlotTracker(M)), + Machine(*ModuleSlotTracker), AnnotationWriter(AAW), + ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) { init(); } -AssemblyWriter::~AssemblyWriter() { } - void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { if (!Operand) { Out << "<null operand!>"; @@ -1553,7 +2128,7 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, void AssemblyWriter::printModule(const Module *M) { Machine.initialize(); - if (shouldPreserveAssemblyUseListOrder()) + if (ShouldPreserveUseListOrder) UseListOrders = predictUseListOrder(M); if (!M->getModuleIdentifier().empty() && @@ -1569,27 +2144,20 @@ void AssemblyWriter::printModule(const Module *M) { Out << "target triple = \"" << M->getTargetTriple() << "\"\n"; if (!M->getModuleInlineAsm().empty()) { - // Split the string into lines, to make it easier to read the .ll file. - std::string Asm = M->getModuleInlineAsm(); - size_t CurPos = 0; - size_t NewLine = Asm.find_first_of('\n', CurPos); Out << '\n'; - while (NewLine != std::string::npos) { + + // Split the string into lines, to make it easier to read the .ll file. + StringRef Asm = M->getModuleInlineAsm(); + do { + StringRef Front; + std::tie(Front, Asm) = Asm.split('\n'); + // We found a newline, print the portion of the asm string from the // last newline up to this newline. Out << "module asm \""; - PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.begin()+NewLine), - Out); + PrintEscapedString(Front, Out); Out << "\"\n"; - CurPos = NewLine+1; - NewLine = Asm.find_first_of('\n', CurPos); - } - std::string rest(Asm.begin()+CurPos, Asm.end()); - if (!rest.empty()) { - Out << "module asm \""; - PrintEscapedString(rest, Out); - Out << "\"\n"; - } + } while (!Asm.empty()); } printTypeIdentities(); @@ -1605,23 +2173,21 @@ void AssemblyWriter::printModule(const Module *M) { // Output all globals. if (!M->global_empty()) Out << '\n'; - for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) { - printGlobal(I); Out << '\n'; + for (const GlobalVariable &GV : M->globals()) { + printGlobal(&GV); Out << '\n'; } // Output all aliases. if (!M->alias_empty()) Out << "\n"; - for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); - I != E; ++I) - printAlias(I); + for (const GlobalAlias &GA : M->aliases()) + printAlias(&GA); // 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); + for (const Function &F : *M) + printFunction(&F); assert(UseListOrders.empty() && "All use-lists should have been consumed"); // Output all attribute groups. @@ -1633,9 +2199,8 @@ void AssemblyWriter::printModule(const Module *M) { // Output named metadata. if (!M->named_metadata_empty()) Out << '\n'; - for (Module::const_named_metadata_iterator I = M->named_metadata_begin(), - E = M->named_metadata_end(); I != E; ++I) - printNamedMDNode(I); + for (const NamedMDNode &Node : M->named_metadata()) + printNamedMDNode(&Node); // Output metadata. if (!Machine.mdn_empty()) { @@ -1644,15 +2209,13 @@ void AssemblyWriter::printModule(const Module *M) { } } -void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { - Out << '!'; - StringRef Name = NMD->getName(); +static void printMetadataIdentifier(StringRef Name, + formatted_raw_ostream &Out) { if (Name.empty()) { Out << "<empty name> "; } else { - if (isalpha(static_cast<unsigned char>(Name[0])) || - Name[0] == '-' || Name[0] == '$' || - Name[0] == '.' || Name[0] == '_') + if (isalpha(static_cast<unsigned char>(Name[0])) || Name[0] == '-' || + Name[0] == '$' || Name[0] == '.' || Name[0] == '_') Out << Name[0]; else Out << '\\' << hexdigit(Name[0] >> 4) << hexdigit(Name[0] & 0x0F); @@ -1665,9 +2228,15 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); } } +} + +void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { + Out << '!'; + printMetadataIdentifier(NMD->getName(), Out); Out << " = !{"; for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - if (i) Out << ", "; + if (i) + Out << ", "; int Slot = Machine.getMetadataSlot(NMD->getOperand(i)); if (Slot == -1) Out << "<badref>"; @@ -1677,7 +2246,6 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { Out << "}\n"; } - static void PrintLinkage(GlobalValue::LinkageTypes LT, formatted_raw_ostream &Out) { switch (LT) { @@ -1697,7 +2265,6 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT, } } - static void PrintVisibility(GlobalValue::VisibilityTypes Vis, formatted_raw_ostream &Out) { switch (Vis) { @@ -1798,13 +2365,9 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { if (GA->isMaterializable()) Out << "; Materializable\n"; - // Don't crash when dumping partially built GA - if (!GA->hasName()) - Out << "<<nameless>> = "; - else { - PrintLLVMName(Out, GA); - Out << " = "; - } + WriteAsOperandInternal(Out, GA, &TypePrinter, &Machine, GA->getParent()); + Out << " = "; + PrintLinkage(GA->getLinkage(), Out); PrintVisibility(GA->getVisibility(), Out); PrintDLLStorageClass(GA->getDLLStorageClass(), Out); @@ -1981,6 +2544,14 @@ void AssemblyWriter::printFunction(const Function *F) { Out << " prologue "; writeOperand(F->getPrologueData(), true); } + if (F->hasPersonalityFn()) { + Out << " personality "; + writeOperand(F->getPersonalityFn(), /*PrintType=*/true); + } + + SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; + F->getAllMetadata(MDs); + printMetadataAttachments(MDs, " "); if (F->isDeclaration()) { Out << '\n'; @@ -2073,10 +2644,26 @@ void AssemblyWriter::printInstructionLine(const Instruction &I) { Out << '\n'; } +/// printGCRelocateComment - print comment after call to the gc.relocate +/// intrinsic indicating base and derived pointer names. +void AssemblyWriter::printGCRelocateComment(const Value &V) { + assert(isGCRelocate(&V)); + GCRelocateOperands GCOps(cast<Instruction>(&V)); + + Out << " ; ("; + writeOperand(GCOps.getBasePtr(), false); + Out << ", "; + writeOperand(GCOps.getDerivedPtr(), false); + Out << ")"; +} + /// printInfoComment - Print a little comment after the instruction indicating /// which slot it occupies. /// void AssemblyWriter::printInfoComment(const Value &V) { + if (isGCRelocate(&V)) + printGCRelocateComment(V); + if (AnnotationWriter) AnnotationWriter->printInfoComment(V, Out); } @@ -2203,8 +2790,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } else if (const LandingPadInst *LPI = dyn_cast<LandingPadInst>(&I)) { Out << ' '; TypePrinter.print(I.getType(), Out); - Out << " personality "; - writeOperand(I.getOperand(0), true); Out << '\n'; + if (LPI->isCleanup() || LPI->getNumClauses() != 0) + Out << '\n'; if (LPI->isCleanup()) Out << " cleanup"; @@ -2228,8 +2815,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } Operand = CI->getCalledValue(); - PointerType *PTy = cast<PointerType>(Operand->getType()); - FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); + FunctionType *FTy = cast<FunctionType>(CI->getFunctionType()); Type *RetTy = FTy->getReturnType(); const AttributeSet &PAL = CI->getAttributes(); @@ -2241,15 +2827,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // and if the return type is not a pointer to a function. // Out << ' '; - if (!FTy->isVarArg() && - (!RetTy->isPointerTy() || - !cast<PointerType>(RetTy)->getElementType()->isFunctionTy())) { - TypePrinter.print(RetTy, Out); - Out << ' '; - writeOperand(Operand, false); - } else { - writeOperand(Operand, true); - } + TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out); + Out << ' '; + writeOperand(Operand, false); Out << '('; for (unsigned op = 0, Eop = CI->getNumArgOperands(); op < Eop; ++op) { if (op > 0) @@ -2269,8 +2849,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) { Operand = II->getCalledValue(); - PointerType *PTy = cast<PointerType>(Operand->getType()); - FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); + FunctionType *FTy = cast<FunctionType>(II->getFunctionType()); Type *RetTy = FTy->getReturnType(); const AttributeSet &PAL = II->getAttributes(); @@ -2288,15 +2867,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // and if the return type is not a pointer to a function. // Out << ' '; - if (!FTy->isVarArg() && - (!RetTy->isPointerTy() || - !cast<PointerType>(RetTy)->getElementType()->isFunctionTy())) { - TypePrinter.print(RetTy, Out); - Out << ' '; - writeOperand(Operand, false); - } else { - writeOperand(Operand, true); - } + TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out); + Out << ' '; + writeOperand(Operand, false); Out << '('; for (unsigned op = 0, Eop = II->getNumArgOperands(); op < Eop; ++op) { if (op) @@ -2318,7 +2891,13 @@ void AssemblyWriter::printInstruction(const Instruction &I) { if (AI->isUsedWithInAlloca()) Out << "inalloca "; TypePrinter.print(AI->getAllocatedType(), Out); - if (!AI->getArraySize() || AI->isArrayAllocation()) { + + // Explicitly write the array size if the code is broken, if it's an array + // allocation, or if the type is not canonical for scalar allocations. The + // latter case prevents the type from mutating when round-tripping through + // assembly. + if (!AI->getArraySize() || AI->isArrayAllocation() || + !AI->getArraySize()->getType()->isIntegerTy(32)) { Out << ", "; writeOperand(AI->getArraySize(), true); } @@ -2340,6 +2919,15 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ", "; TypePrinter.print(I.getType(), Out); } else if (Operand) { // Print the normal way. + if (const auto *GEP = dyn_cast<GetElementPtrInst>(&I)) { + Out << ' '; + TypePrinter.print(GEP->getSourceElementType(), Out); + Out << ','; + } else if (const auto *LI = dyn_cast<LoadInst>(&I)) { + Out << ' '; + TypePrinter.print(LI->getType(), Out); + Out << ','; + } // PrintAllTypes - Instructions who have operands of all the same type // omit the type from all but the first operand. If the instruction has @@ -2398,50 +2986,38 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // Print Metadata info. SmallVector<std::pair<unsigned, MDNode *>, 4> InstMD; I.getAllMetadata(InstMD); - if (!InstMD.empty()) { - SmallVector<StringRef, 8> MDNames; - I.getType()->getContext().getMDKindNames(MDNames); - for (unsigned i = 0, e = InstMD.size(); i != e; ++i) { - unsigned Kind = InstMD[i].first; - if (Kind < MDNames.size()) { - Out << ", !" << MDNames[Kind]; - } else { - Out << ", !<unknown kind #" << Kind << ">"; - } - Out << ' '; - WriteAsOperandInternal(Out, InstMD[i].second, &TypePrinter, &Machine, - TheModule); - } - } + printMetadataAttachments(InstMD, ", "); + + // Print a nice comment. printInfoComment(I); } -static void WriteMDNodeComment(const MDNode *Node, - formatted_raw_ostream &Out) { - if (Node->getNumOperands() < 1) - return; - - Metadata *Op = Node->getOperand(0); - if (!Op || !isa<MDString>(Op)) +void AssemblyWriter::printMetadataAttachments( + const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs, + StringRef Separator) { + if (MDs.empty()) return; - DIDescriptor Desc(Node); - if (!Desc.Verify()) - return; + if (MDNames.empty()) + TheModule->getMDKindNames(MDNames); - unsigned Tag = Desc.getTag(); - Out.PadToColumn(50); - if (dwarf::TagString(Tag)) { - Out << "; "; - Desc.print(Out); - } else if (Tag == dwarf::DW_TAG_user_base) { - Out << "; [ DW_TAG_user_base ]"; + for (const auto &I : MDs) { + unsigned Kind = I.first; + Out << Separator; + if (Kind < MDNames.size()) { + Out << "!"; + printMetadataIdentifier(MDNames[Kind], Out); + } else + Out << "!<unknown kind #" << Kind << ">"; + Out << ' '; + WriteAsOperandInternal(Out, I.second, &TypePrinter, &Machine, TheModule); } } void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) { Out << '!' << Slot << " = "; printMDNodeBody(Node); + Out << "\n"; } void AssemblyWriter::writeAllMDNodes() { @@ -2458,8 +3034,6 @@ void AssemblyWriter::writeAllMDNodes() { void AssemblyWriter::printMDNodeBody(const MDNode *Node) { WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule); - WriteMDNodeComment(Node, Out); - Out << "\n"; } void AssemblyWriter::writeAllAttributeGroups() { @@ -2476,8 +3050,6 @@ void AssemblyWriter::writeAllAttributeGroups() { << I->first.getAsString(AttributeSet::FunctionIndex, true) << " }\n"; } -} // namespace llvm - void AssemblyWriter::printUseListOrder(const UseListOrder &Order) { bool IsInFunction = Machine.getFunction(); if (IsInFunction) @@ -2521,10 +3093,18 @@ void AssemblyWriter::printUseLists(const Function *F) { // External Interface declarations //===----------------------------------------------------------------------===// -void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const { +void Function::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const { + SlotTracker SlotTable(this->getParent()); + formatted_raw_ostream OS(ROS); + AssemblyWriter W(OS, SlotTable, this->getParent(), AAW); + W.printFunction(this); +} + +void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder) const { SlotTracker SlotTable(this); formatted_raw_ostream OS(ROS); - AssemblyWriter W(OS, SlotTable, this, AAW); + AssemblyWriter W(OS, SlotTable, this, AAW, ShouldPreserveUseListOrder); W.printModule(this); } @@ -2572,11 +3152,24 @@ void Type::print(raw_ostream &OS) const { } } +static bool isReferencingMDNode(const Instruction &I) { + if (const auto *CI = dyn_cast<CallInst>(&I)) + if (Function *F = CI->getCalledFunction()) + if (F->isIntrinsic()) + for (auto &Op : I.operands()) + if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op)) + if (isa<MDNode>(V->getMetadata())) + return true; + return false; +} + void Value::print(raw_ostream &ROS) const { formatted_raw_ostream OS(ROS); if (const Instruction *I = dyn_cast<Instruction>(this)) { const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr; - SlotTracker SlotTable(F); + SlotTracker SlotTable( + F, + /* ShouldInitializeAllMetadata */ isReferencingMDNode(*I)); AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr); W.printInstruction(*I); } else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) { @@ -2584,7 +3177,8 @@ void Value::print(raw_ostream &ROS) const { AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr); W.printBasicBlock(BB); } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) { - SlotTracker SlotTable(GV->getParent()); + SlotTracker SlotTable(GV->getParent(), + /* ShouldInitializeAllMetadata */ isa<Function>(GV)); AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr); if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV)) W.printGlobal(V); @@ -2593,7 +3187,7 @@ void Value::print(raw_ostream &ROS) const { else W.printAlias(cast<GlobalAlias>(GV)); } else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) { - V->getMetadata()->print(ROS); + V->getMetadata()->print(ROS, getModuleFromVal(V)); } else if (const Constant *C = dyn_cast<Constant>(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); @@ -2609,8 +3203,9 @@ void Value::print(raw_ostream &ROS) const { void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const { // Fast path: Don't construct and populate a TypePrinting object if we // won't be needing any types printed. - if (!PrintType && ((!isa<Constant>(this) && !isa<MetadataAsValue>(this)) || - hasName() || isa<GlobalValue>(this))) { + bool IsMetadata = isa<MetadataAsValue>(this); + if (!PrintType && ((!isa<Constant>(this) && !IsMetadata) || hasName() || + isa<GlobalValue>(this))) { WriteAsOperandInternal(O, this, nullptr, nullptr, M); return; } @@ -2626,51 +3221,62 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) cons O << ' '; } - WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M); + SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ IsMetadata); + WriteAsOperandInternal(O, this, &TypePrinter, &Machine, M); } -void Metadata::print(raw_ostream &ROS) const { +static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, + const Module *M, bool OnlyAsOperand) { formatted_raw_ostream OS(ROS); - if (auto *N = dyn_cast<MDNode>(this)) { - SlotTracker SlotTable(static_cast<Function *>(nullptr)); - AssemblyWriter W(OS, SlotTable, nullptr, nullptr); - W.printMDNodeBody(N); + auto *N = dyn_cast<MDNode>(&MD); + TypePrinting TypePrinter; + SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ N); + if (M) + TypePrinter.incorporateTypes(*M); + + WriteAsOperandInternal(OS, &MD, &TypePrinter, &Machine, M, + /* FromValue */ true); + if (OnlyAsOperand || !N) return; - } - printAsOperand(OS); + + OS << " = "; + WriteMDNodeBodyInternal(OS, N, &TypePrinter, &Machine, M); } -void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType, - const Module *M) const { - formatted_raw_ostream OS(ROS); +void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const { + printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ true); +} - std::unique_ptr<TypePrinting> TypePrinter; - if (PrintType) { - TypePrinter.reset(new TypePrinting); - if (M) - TypePrinter->incorporateTypes(*M); - } - WriteAsOperandInternal(OS, this, TypePrinter.get(), nullptr, M, - /* FromValue */ true); +void Metadata::print(raw_ostream &OS, const Module *M) const { + printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ false); } // Value::dump - allow easy printing of Values from the debugger. +LLVM_DUMP_METHOD void Value::dump() const { print(dbgs()); dbgs() << '\n'; } // Type::dump - allow easy printing of Types from the debugger. +LLVM_DUMP_METHOD void Type::dump() const { print(dbgs()); dbgs() << '\n'; } // Module::dump() - Allow printing of Modules from the debugger. +LLVM_DUMP_METHOD void Module::dump() const { print(dbgs(), nullptr); } // \brief Allow printing of Comdats from the debugger. +LLVM_DUMP_METHOD void Comdat::dump() const { print(dbgs()); } // NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger. +LLVM_DUMP_METHOD void NamedMDNode::dump() const { print(dbgs()); } -void Metadata::dump() const { - print(dbgs()); +LLVM_DUMP_METHOD +void Metadata::dump() const { dump(nullptr); } + +LLVM_DUMP_METHOD +void Metadata::dump(const Module *M) const { + print(dbgs(), M); dbgs() << '\n'; } diff --git a/contrib/llvm/lib/IR/AsmWriter.h b/contrib/llvm/lib/IR/AsmWriter.h deleted file mode 100644 index 60da5ad..0000000 --- a/contrib/llvm/lib/IR/AsmWriter.h +++ /dev/null @@ -1,129 +0,0 @@ -//===-- llvm/IR/AsmWriter.h - Printing LLVM IR as an assembly file - C++ --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This files defines the interface for the AssemblyWriter class used to print -// LLVM IR and various helper classes that are used in printing. -// -//===----------------------------------------------------------------------===// - -#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 { - -class BasicBlock; -class Function; -class GlobalValue; -class Comdat; -class Module; -class NamedMDNode; -class Value; -class SlotTracker; - -/// Create a new SlotTracker for a Module -SlotTracker *createSlotTracker(const Module *M); - -//===----------------------------------------------------------------------===// -// TypePrinting Class: Type printing machinery -//===----------------------------------------------------------------------===// - -class TypePrinting { - TypePrinting(const TypePrinting &) LLVM_DELETED_FUNCTION; - void operator=(const TypePrinting&) LLVM_DELETED_FUNCTION; -public: - - /// NamedTypes - The named types that are used by the current module. - TypeFinder NamedTypes; - - /// NumberedTypes - The numbered types, along with their value. - DenseMap<StructType*, unsigned> NumberedTypes; - - - TypePrinting() {} - ~TypePrinting() {} - - void incorporateTypes(const Module &M); - - void print(Type *Ty, raw_ostream &OS); - - void printStructBody(StructType *Ty, raw_ostream &OS); -}; - -class AssemblyWriter { -protected: - formatted_raw_ostream &Out; - const Module *TheModule; - -private: - std::unique_ptr<SlotTracker> ModuleSlotTracker; - SlotTracker &Machine; - TypePrinting TypePrinter; - AssemblyAnnotationWriter *AnnotationWriter; - SetVector<const Comdat *> Comdats; - UseListOrderStack UseListOrders; - -public: - /// Construct an AssemblyWriter with an external SlotTracker - AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, - const Module *M, AssemblyAnnotationWriter *AAW); - - /// Construct an AssemblyWriter with an internally allocated SlotTracker - AssemblyWriter(formatted_raw_ostream &o, const Module *M, - AssemblyAnnotationWriter *AAW); - - virtual ~AssemblyWriter(); - - void printMDNodeBody(const MDNode *MD); - void printNamedMDNode(const NamedMDNode *NMD); - - void printModule(const Module *M); - - void writeOperand(const Value *Op, bool PrintType); - void writeParamOperand(const Value *Operand, AttributeSet Attrs,unsigned Idx); - void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope); - void writeAtomicCmpXchg(AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, - SynchronizationScope SynchScope); - - void writeAllMDNodes(); - void writeMDNode(unsigned Slot, const MDNode *Node); - void writeAllAttributeGroups(); - - void printTypeIdentities(); - void printGlobal(const GlobalVariable *GV); - void printAlias(const GlobalAlias *GV); - void printComdat(const Comdat *C); - void printFunction(const Function *F); - void printArgument(const Argument *FA, AttributeSet Attrs, unsigned Idx); - void printBasicBlock(const BasicBlock *BB); - void printInstructionLine(const Instruction &I); - void printInstruction(const Instruction &I); - - void printUseListOrder(const UseListOrder &Order); - void printUseLists(const Function *F); - -private: - void init(); - - // printInfoComment - Print a little comment after the instruction indicating - // which slot it occupies. - void printInfoComment(const Value &V); -}; - -} // namespace llvm - -#endif diff --git a/contrib/llvm/lib/IR/AttributeImpl.h b/contrib/llvm/lib/IR/AttributeImpl.h index 0448dc17..8159dce 100644 --- a/contrib/llvm/lib/IR/AttributeImpl.h +++ b/contrib/llvm/lib/IR/AttributeImpl.h @@ -33,8 +33,8 @@ class AttributeImpl : public FoldingSetNode { unsigned char KindID; ///< Holds the AttrEntryKind of the attribute // AttributesImpl is uniqued, these should not be publicly available. - void operator=(const AttributeImpl &) LLVM_DELETED_FUNCTION; - AttributeImpl(const AttributeImpl &) LLVM_DELETED_FUNCTION; + void operator=(const AttributeImpl &) = delete; + AttributeImpl(const AttributeImpl &) = delete; protected: enum AttrEntryKind { @@ -115,10 +115,10 @@ class IntAttributeImpl : public EnumAttributeImpl { public: IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { - assert( - (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || - Kind == Attribute::Dereferenceable) && - "Wrong kind for int attribute!"); + assert((Kind == Attribute::Alignment || Kind == Attribute::StackAlignment || + Kind == Attribute::Dereferenceable || + Kind == Attribute::DereferenceableOrNull) && + "Wrong kind for int attribute!"); } uint64_t getValue() const { return Val; } @@ -151,8 +151,8 @@ class AttributeSetNode : public FoldingSetNode { } // AttributesSetNode is uniqued, these should not be publicly available. - void operator=(const AttributeSetNode &) LLVM_DELETED_FUNCTION; - AttributeSetNode(const AttributeSetNode &) LLVM_DELETED_FUNCTION; + void operator=(const AttributeSetNode &) = delete; + AttributeSetNode(const AttributeSetNode &) = delete; public: static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs); @@ -166,6 +166,7 @@ public: unsigned getAlignment() const; unsigned getStackAlignment() const; uint64_t getDereferenceableBytes() const; + uint64_t getDereferenceableOrNullBytes() const; std::string getAsString(bool InAttrGrp) const; typedef const Attribute *iterator; @@ -180,6 +181,9 @@ public: AttrList[I].Profile(ID); } }; +static_assert( + AlignOf<AttributeSetNode>::Alignment >= AlignOf<Attribute>::Alignment, + "Alignment is insufficient for objects appended to AttributeSetNode"); //===----------------------------------------------------------------------===// /// \class @@ -188,9 +192,11 @@ public: class AttributeSetImpl : public FoldingSetNode { friend class AttributeSet; - LLVMContext &Context; - +public: typedef std::pair<unsigned, AttributeSetNode*> IndexAttrPair; + +private: + LLVMContext &Context; unsigned NumAttrs; ///< Number of entries in this set. /// \brief Return a pointer to the IndexAttrPair for the specified slot. @@ -199,12 +205,13 @@ class AttributeSetImpl : public FoldingSetNode { } // AttributesSet is uniqued, these should not be publicly available. - void operator=(const AttributeSetImpl &) LLVM_DELETED_FUNCTION; - AttributeSetImpl(const AttributeSetImpl &) LLVM_DELETED_FUNCTION; + void operator=(const AttributeSetImpl &) = delete; + AttributeSetImpl(const AttributeSetImpl &) = delete; public: AttributeSetImpl(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs) : Context(C), NumAttrs(Attrs.size()) { + #ifndef NDEBUG if (Attrs.size() >= 2) { for (const std::pair<unsigned, AttributeSetNode *> *i = Attrs.begin() + 1, @@ -266,7 +273,11 @@ public: void dump() const; }; +static_assert( + AlignOf<AttributeSetImpl>::Alignment >= + AlignOf<AttributeSetImpl::IndexAttrPair>::Alignment, + "Alignment is insufficient for objects appended to AttributeSetImpl"); -} // end llvm namespace +} // namespace llvm #endif diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp index 04545ea..c3032f4 100644 --- a/contrib/llvm/lib/IR/Attributes.cpp +++ b/contrib/llvm/lib/IR/Attributes.cpp @@ -94,6 +94,12 @@ Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context, return get(Context, Dereferenceable, Bytes); } +Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context, + uint64_t Bytes) { + assert(Bytes && "Bytes must be non-zero."); + return get(Context, DereferenceableOrNull, Bytes); +} + //===----------------------------------------------------------------------===// // Attribute Accessor Methods //===----------------------------------------------------------------------===// @@ -170,6 +176,13 @@ uint64_t Attribute::getDereferenceableBytes() const { return pImpl->getValueAsInt(); } +uint64_t Attribute::getDereferenceableOrNullBytes() const { + assert(hasAttribute(Attribute::DereferenceableOrNull) && + "Trying to get dereferenceable bytes from " + "non-dereferenceable attribute!"); + return pImpl->getValueAsInt(); +} + std::string Attribute::getAsString(bool InAttrGrp) const { if (!pImpl) return ""; @@ -181,6 +194,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "builtin"; if (hasAttribute(Attribute::ByVal)) return "byval"; + if (hasAttribute(Attribute::Convergent)) + return "convergent"; if (hasAttribute(Attribute::InAlloca)) return "inalloca"; if (hasAttribute(Attribute::InlineHint)) @@ -237,6 +252,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "sspreq"; if (hasAttribute(Attribute::StackProtectStrong)) return "sspstrong"; + if (hasAttribute(Attribute::SafeStack)) + return "safestack"; if (hasAttribute(Attribute::StructRet)) return "sret"; if (hasAttribute(Attribute::SanitizeThread)) @@ -263,9 +280,9 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return Result; } - if (hasAttribute(Attribute::StackAlignment)) { + auto AttrWithBytesToString = [&](const char *Name) { std::string Result; - Result += "alignstack"; + Result += Name; if (InAttrGrp) { Result += "="; Result += utostr(getValueAsInt()); @@ -275,21 +292,16 @@ std::string Attribute::getAsString(bool InAttrGrp) const { Result += ")"; } 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; - } + if (hasAttribute(Attribute::StackAlignment)) + return AttrWithBytesToString("alignstack"); + + if (hasAttribute(Attribute::Dereferenceable)) + return AttrWithBytesToString("dereferenceable"); + + if (hasAttribute(Attribute::DereferenceableOrNull)) + return AttrWithBytesToString("dereferenceable_or_null"); // Convert target-dependent attributes to strings of the form: // @@ -298,12 +310,12 @@ std::string Attribute::getAsString(bool InAttrGrp) const { // if (isStringAttribute()) { std::string Result; - Result += '\"' + getKindAsString().str() + '"'; + Result += (Twine('"') + getKindAsString() + Twine('"')).str(); StringRef Val = pImpl->getValueAsString(); if (Val.empty()) return Result; - Result += "=\"" + Val.str() + '"'; + Result += ("=\"" + Val + Twine('"')).str(); return Result; } @@ -426,8 +438,15 @@ 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::Convergent: return 1ULL << 46; + case Attribute::SafeStack: return 1ULL << 47; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); + break; + case Attribute::DereferenceableOrNull: + llvm_unreachable("dereferenceable_or_null attribute not supported in raw " + "format"); + break; } llvm_unreachable("Unsupported attribute type"); } @@ -519,6 +538,13 @@ uint64_t AttributeSetNode::getDereferenceableBytes() const { return 0; } +uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->hasAttribute(Attribute::DereferenceableOrNull)) + return I->getDereferenceableOrNullBytes(); + return 0; +} + std::string AttributeSetNode::getAsString(bool InAttrGrp) const { std::string Str; for (iterator I = begin(), E = end(); I != E; ++I) { @@ -663,6 +689,10 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, Attrs.push_back(std::make_pair(Index, Attribute::getWithDereferenceableBytes(C, B.getDereferenceableBytes()))); + else if (Kind == Attribute::DereferenceableOrNull) + Attrs.push_back( + std::make_pair(Index, Attribute::getWithDereferenceableOrNullBytes( + C, B.getDereferenceableOrNullBytes()))); else Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind))); } @@ -795,12 +825,10 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index, if (!pImpl) return AttributeSet(); if (!Attrs.pImpl) return *this; -#ifndef NDEBUG // FIXME it is not obvious how this should work for alignment. // For now, say we can't pass in alignment, which no current use does. assert(!Attrs.hasAttribute(Index, Attribute::Alignment) && "Attempt to change alignment!"); -#endif // Add the attribute slots before the one we're trying to add. SmallVector<AttributeSet, 4> AttrSet; @@ -835,6 +863,57 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index, return get(C, AttrSet); } +AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index, + const AttrBuilder &Attrs) const { + if (!pImpl) return AttributeSet(); + + // FIXME it is not obvious how this should work for alignment. + // For now, say we can't pass in alignment, which no current use does. + assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!"); + + // Add the attribute slots before the one we're trying to add. + SmallVector<AttributeSet, 4> AttrSet; + uint64_t NumAttrs = pImpl->getNumAttributes(); + AttributeSet AS; + uint64_t LastIndex = 0; + for (unsigned I = 0, E = NumAttrs; I != E; ++I) { + if (getSlotIndex(I) >= Index) { + if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); + break; + } + LastIndex = I + 1; + AttrSet.push_back(getSlotAttributes(I)); + } + + // Now remove the attribute from the correct slot. There may already be an + // AttributeSet there. + AttrBuilder B(AS, Index); + B.remove(Attrs); + + AttrSet.push_back(AttributeSet::get(C, Index, B)); + + // Add the remaining attribute slots. + for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) + AttrSet.push_back(getSlotAttributes(I)); + + return get(C, AttrSet); +} + +AttributeSet AttributeSet::addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const { + llvm::AttrBuilder B; + B.addDereferenceableAttr(Bytes); + return addAttributes(C, Index, AttributeSet::get(C, Index, B)); +} + +AttributeSet AttributeSet::addDereferenceableOrNullAttr(LLVMContext &C, + unsigned Index, + uint64_t Bytes) const { + llvm::AttrBuilder B; + B.addDereferenceableOrNullAttr(Bytes); + return addAttributes(C, Index, AttributeSet::get(C, Index, B)); +} + //===----------------------------------------------------------------------===// // AttributeSet Accessor Methods //===----------------------------------------------------------------------===// @@ -925,6 +1004,11 @@ uint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const { return ASN ? ASN->getDereferenceableBytes() : 0; } +uint64_t AttributeSet::getDereferenceableOrNullBytes(unsigned Index) const { + AttributeSetNode *ASN = getAttributes(Index); + return ASN ? ASN->getDereferenceableOrNullBytes() : 0; +} + std::string AttributeSet::getAsString(unsigned Index, bool InAttrGrp) const { AttributeSetNode *ASN = getAttributes(Index); @@ -1004,7 +1088,8 @@ void AttributeSet::dump() const { //===----------------------------------------------------------------------===// AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { AttributeSetImpl *pImpl = AS.pImpl; if (!pImpl) return; @@ -1021,7 +1106,7 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) void AttrBuilder::clear() { Attrs.reset(); - Alignment = StackAlignment = DerefBytes = 0; + Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0; } AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { @@ -1048,6 +1133,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { StackAlignment = Attr.getStackAlignment(); else if (Kind == Attribute::Dereferenceable) DerefBytes = Attr.getDereferenceableBytes(); + else if (Kind == Attribute::DereferenceableOrNull) + DerefOrNullBytes = Attr.getDereferenceableOrNullBytes(); return *this; } @@ -1066,6 +1153,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { StackAlignment = 0; else if (Val == Attribute::Dereferenceable) DerefBytes = 0; + else if (Val == Attribute::DereferenceableOrNull) + DerefOrNullBytes = 0; return *this; } @@ -1092,6 +1181,8 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) { StackAlignment = 0; else if (Kind == Attribute::Dereferenceable) DerefBytes = 0; + else if (Kind == Attribute::DereferenceableOrNull) + DerefOrNullBytes = 0; } else { assert(Attr.isStringAttribute() && "Invalid attribute type!"); std::map<std::string, std::string>::iterator @@ -1142,6 +1233,15 @@ AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) { return *this; } +AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) { + if (Bytes == 0) + return *this; + + Attrs[Attribute::DereferenceableOrNull] = true; + DerefOrNullBytes = Bytes; + return *this; +} + AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { // FIXME: What if both have alignments, but they don't match?! if (!Alignment) @@ -1153,15 +1253,52 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { if (!DerefBytes) DerefBytes = B.DerefBytes; + if (!DerefOrNullBytes) + DerefOrNullBytes = B.DerefOrNullBytes; + Attrs |= B.Attrs; - for (td_const_iterator I = B.TargetDepAttrs.begin(), - E = B.TargetDepAttrs.end(); I != E; ++I) - TargetDepAttrs[I->first] = I->second; + for (auto I : B.td_attrs()) + TargetDepAttrs[I.first] = I.second; + + return *this; +} + +AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { + // FIXME: What if both have alignments, but they don't match?! + if (B.Alignment) + Alignment = 0; + + if (B.StackAlignment) + StackAlignment = 0; + + if (B.DerefBytes) + DerefBytes = 0; + + if (B.DerefOrNullBytes) + DerefOrNullBytes = 0; + + Attrs &= ~B.Attrs; + + for (auto I : B.td_attrs()) + TargetDepAttrs.erase(I.first); return *this; } +bool AttrBuilder::overlaps(const AttrBuilder &B) const { + // First check if any of the target independent attributes overlap. + if ((Attrs & B.Attrs).any()) + return true; + + // Then check if any target dependent ones do. + for (auto I : td_attrs()) + if (B.contains(I.first)) + return true; + + return false; +} + bool AttrBuilder::contains(StringRef A) const { return TargetDepAttrs.find(A) != TargetDepAttrs.end(); } @@ -1218,7 +1355,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) + if (I == Attribute::Dereferenceable || + I == Attribute::DereferenceableOrNull) continue; if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) { Attrs[I] = true; @@ -1238,7 +1376,7 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { //===----------------------------------------------------------------------===// /// \brief Which attributes cannot be applied to a type. -AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { +AttrBuilder AttributeFuncs::typeIncompatible(const Type *Ty) { AttrBuilder Incompatible; if (!Ty->isIntegerTy()) @@ -1254,10 +1392,11 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { .addAttribute(Attribute::NoCapture) .addAttribute(Attribute::NonNull) .addDereferenceableAttr(1) // the int here is ignored + .addDereferenceableOrNullAttr(1) // the int here is ignored .addAttribute(Attribute::ReadNone) .addAttribute(Attribute::ReadOnly) .addAttribute(Attribute::StructRet) .addAttribute(Attribute::InAlloca); - return AttributeSet::get(Ty->getContext(), Index, Incompatible); + return Incompatible; } diff --git a/contrib/llvm/lib/IR/AutoUpgrade.cpp b/contrib/llvm/lib/IR/AutoUpgrade.cpp index e3544df..70a5518 100644 --- a/contrib/llvm/lib/IR/AutoUpgrade.cpp +++ b/contrib/llvm/lib/IR/AutoUpgrade.cpp @@ -7,7 +7,9 @@ // //===----------------------------------------------------------------------===// // -// This file implements the auto-upgrade helper functions +// This file implements the auto-upgrade helper functions. +// This is where deprecated IR intrinsics and other IR features are updated to +// current specifications. // //===----------------------------------------------------------------------===// @@ -107,19 +109,6 @@ 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 @@ -141,6 +130,14 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { Name.startswith("x86.avx2.pcmpeq.") || Name.startswith("x86.avx2.pcmpgt.") || Name.startswith("x86.avx.vpermil.") || + Name == "x86.avx.vinsertf128.pd.256" || + Name == "x86.avx.vinsertf128.ps.256" || + Name == "x86.avx.vinsertf128.si.256" || + Name == "x86.avx2.vinserti128" || + Name == "x86.avx.vextractf128.pd.256" || + Name == "x86.avx.vextractf128.ps.256" || + Name == "x86.avx.vextractf128.si.256" || + Name == "x86.avx2.vextracti128" || Name == "x86.avx.movnt.dq.256" || Name == "x86.avx.movnt.pd.256" || Name == "x86.avx.movnt.ps.256" || @@ -148,6 +145,23 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { Name == "x86.avx.vbroadcast.ss" || Name == "x86.avx.vbroadcast.ss.256" || Name == "x86.avx.vbroadcast.sd.256" || + Name == "x86.sse2.psll.dq" || + Name == "x86.sse2.psrl.dq" || + Name == "x86.avx2.psll.dq" || + Name == "x86.avx2.psrl.dq" || + Name == "x86.sse2.psll.dq.bs" || + Name == "x86.sse2.psrl.dq.bs" || + Name == "x86.avx2.psll.dq.bs" || + Name == "x86.avx2.psrl.dq.bs" || + Name == "x86.sse41.pblendw" || + Name == "x86.sse41.blendpd" || + Name == "x86.sse41.blendps" || + Name == "x86.avx.blend.pd.256" || + Name == "x86.avx.blend.ps.256" || + Name == "x86.avx2.pblendw" || + Name == "x86.avx2.pblendd.128" || + Name == "x86.avx2.pblendd.256" || + Name == "x86.avx2.vbroadcasti128" || (Name.startswith("x86.xop.vpcom") && F->arg_size() == 2)) { NewFn = nullptr; return true; @@ -161,17 +175,8 @@ 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 + // Several blend and other instructions with masks 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); @@ -184,24 +189,9 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&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); @@ -243,9 +233,8 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) { // Upgrade intrinsic attributes. This does not change the function. if (NewFn) F = NewFn; - if (unsigned id = F->getIntrinsicID()) - F->setAttributes(Intrinsic::getAttributes(F->getContext(), - (Intrinsic::ID)id)); + if (Intrinsic::ID id = F->getIntrinsicID()) + F->setAttributes(Intrinsic::getAttributes(F->getContext(), id)); return Upgraded; } @@ -254,21 +243,78 @@ bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { 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)); +// Handles upgrading SSE2 and AVX2 PSLLDQ intrinsics by converting them +// to byte shuffles. +static Value *UpgradeX86PSLLDQIntrinsics(IRBuilder<> &Builder, LLVMContext &C, + Value *Op, unsigned NumLanes, + unsigned Shift) { + // Each lane is 16 bytes. + unsigned NumElts = NumLanes * 16; + + // Bitcast from a 64-bit element type to a byte element type. + Op = Builder.CreateBitCast(Op, + VectorType::get(Type::getInt8Ty(C), NumElts), + "cast"); + // We'll be shuffling in zeroes. + Value *Res = ConstantVector::getSplat(NumElts, Builder.getInt8(0)); + + // If shift is less than 16, emit a shuffle to move the bytes. Otherwise, + // we'll just return the zero vector. + if (Shift < 16) { + SmallVector<Constant*, 32> Idxs; + // 256-bit version is split into two 16-byte lanes. + for (unsigned l = 0; l != NumElts; l += 16) + for (unsigned i = 0; i != 16; ++i) { + unsigned Idx = NumElts + i - Shift; + if (Idx < NumElts) + Idx -= NumElts - 16; // end of lane, switch operand. + Idxs.push_back(Builder.getInt32(Idx + l)); + } + + Res = Builder.CreateShuffleVector(Res, Op, ConstantVector::get(Idxs)); + } + + // Bitcast back to a 64-bit element type. + return Builder.CreateBitCast(Res, + VectorType::get(Type::getInt64Ty(C), 2*NumLanes), + "cast"); } -static MetadataAsValue *getExpression(Value *VarOperand, Function *F) { - // Old-style DIVariables have an optional expression as the 8th element. - DIExpression Expr(getNodeField( - cast<MDNode>(cast<MetadataAsValue>(VarOperand)->getMetadata()), 8)); - if (!Expr) { - DIBuilder DIB(*F->getParent(), /*AllowUnresolved*/ false); - Expr = DIB.createExpression(); +// Handles upgrading SSE2 and AVX2 PSRLDQ intrinsics by converting them +// to byte shuffles. +static Value *UpgradeX86PSRLDQIntrinsics(IRBuilder<> &Builder, LLVMContext &C, + Value *Op, unsigned NumLanes, + unsigned Shift) { + // Each lane is 16 bytes. + unsigned NumElts = NumLanes * 16; + + // Bitcast from a 64-bit element type to a byte element type. + Op = Builder.CreateBitCast(Op, + VectorType::get(Type::getInt8Ty(C), NumElts), + "cast"); + // We'll be shuffling in zeroes. + Value *Res = ConstantVector::getSplat(NumElts, Builder.getInt8(0)); + + // If shift is less than 16, emit a shuffle to move the bytes. Otherwise, + // we'll just return the zero vector. + if (Shift < 16) { + SmallVector<Constant*, 32> Idxs; + // 256-bit version is split into two 16-byte lanes. + for (unsigned l = 0; l != NumElts; l += 16) + for (unsigned i = 0; i != 16; ++i) { + unsigned Idx = i + Shift; + if (Idx >= 16) + Idx += NumElts - 16; // end of lane, switch operand. + Idxs.push_back(Builder.getInt32(Idx + l)); + } + + Res = Builder.CreateShuffleVector(Op, Res, ConstantVector::get(Idxs)); } - return MetadataAsValue::get(F->getContext(), Expr); + + // Bitcast back to a 64-bit element type. + return Builder.CreateBitCast(Res, + VectorType::get(Type::getInt64Ty(C), 2*NumLanes), + "cast"); } // UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the @@ -361,21 +407,22 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Imm = 4; else if (Name.startswith("ne")) Imm = 5; - else if (Name.startswith("true")) - Imm = 6; else if (Name.startswith("false")) + Imm = 6; + else if (Name.startswith("true")) Imm = 7; else llvm_unreachable("Unknown condition"); Function *VPCOM = Intrinsic::getDeclaration(F->getParent(), intID); - Rep = Builder.CreateCall3(VPCOM, CI->getArgOperand(0), - CI->getArgOperand(1), Builder.getInt8(Imm)); + Rep = + Builder.CreateCall(VPCOM, {CI->getArgOperand(0), CI->getArgOperand(1), + Builder.getInt8(Imm)}); } else if (Name == "llvm.x86.sse42.crc32.64.8") { Function *CRC32 = Intrinsic::getDeclaration(F->getParent(), Intrinsic::x86_sse42_crc32_32_8); Value *Trunc0 = Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C)); - Rep = Builder.CreateCall2(CRC32, Trunc0, CI->getArgOperand(1)); + Rep = Builder.CreateCall(CRC32, {Trunc0, CI->getArgOperand(1)}); Rep = Builder.CreateZExt(Rep, CI->getType(), ""); } else if (Name.startswith("llvm.x86.avx.vbroadcast")) { // Replace broadcasts with a series of insertelements. @@ -384,12 +431,149 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { unsigned EltNum = VecTy->getVectorNumElements(); Value *Cast = Builder.CreateBitCast(CI->getArgOperand(0), EltTy->getPointerTo()); - Value *Load = Builder.CreateLoad(Cast); + Value *Load = Builder.CreateLoad(EltTy, Cast); Type *I32Ty = Type::getInt32Ty(C); Rep = UndefValue::get(VecTy); for (unsigned I = 0; I < EltNum; ++I) Rep = Builder.CreateInsertElement(Rep, Load, ConstantInt::get(I32Ty, I)); + } else if (Name == "llvm.x86.avx2.vbroadcasti128") { + // Replace vbroadcasts with a vector shuffle. + Type *VT = VectorType::get(Type::getInt64Ty(C), 2); + Value *Op = Builder.CreatePointerCast(CI->getArgOperand(0), + PointerType::getUnqual(VT)); + Value *Load = Builder.CreateLoad(VT, Op); + const int Idxs[4] = { 0, 1, 0, 1 }; + Rep = Builder.CreateShuffleVector(Load, UndefValue::get(Load->getType()), + Idxs); + } else if (Name == "llvm.x86.sse2.psll.dq") { + // 128-bit shift left specified in bits. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSLLDQIntrinsics(Builder, C, CI->getArgOperand(0), 1, + Shift / 8); // Shift is in bits. + } else if (Name == "llvm.x86.sse2.psrl.dq") { + // 128-bit shift right specified in bits. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSRLDQIntrinsics(Builder, C, CI->getArgOperand(0), 1, + Shift / 8); // Shift is in bits. + } else if (Name == "llvm.x86.avx2.psll.dq") { + // 256-bit shift left specified in bits. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSLLDQIntrinsics(Builder, C, CI->getArgOperand(0), 2, + Shift / 8); // Shift is in bits. + } else if (Name == "llvm.x86.avx2.psrl.dq") { + // 256-bit shift right specified in bits. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSRLDQIntrinsics(Builder, C, CI->getArgOperand(0), 2, + Shift / 8); // Shift is in bits. + } else if (Name == "llvm.x86.sse2.psll.dq.bs") { + // 128-bit shift left specified in bytes. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSLLDQIntrinsics(Builder, C, CI->getArgOperand(0), 1, + Shift); + } else if (Name == "llvm.x86.sse2.psrl.dq.bs") { + // 128-bit shift right specified in bytes. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSRLDQIntrinsics(Builder, C, CI->getArgOperand(0), 1, + Shift); + } else if (Name == "llvm.x86.avx2.psll.dq.bs") { + // 256-bit shift left specified in bytes. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSLLDQIntrinsics(Builder, C, CI->getArgOperand(0), 2, + Shift); + } else if (Name == "llvm.x86.avx2.psrl.dq.bs") { + // 256-bit shift right specified in bytes. + unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + Rep = UpgradeX86PSRLDQIntrinsics(Builder, C, CI->getArgOperand(0), 2, + Shift); + } else if (Name == "llvm.x86.sse41.pblendw" || + Name == "llvm.x86.sse41.blendpd" || + Name == "llvm.x86.sse41.blendps" || + Name == "llvm.x86.avx.blend.pd.256" || + Name == "llvm.x86.avx.blend.ps.256" || + Name == "llvm.x86.avx2.pblendw" || + Name == "llvm.x86.avx2.pblendd.128" || + Name == "llvm.x86.avx2.pblendd.256") { + Value *Op0 = CI->getArgOperand(0); + Value *Op1 = CI->getArgOperand(1); + unsigned Imm = cast <ConstantInt>(CI->getArgOperand(2))->getZExtValue(); + VectorType *VecTy = cast<VectorType>(CI->getType()); + unsigned NumElts = VecTy->getNumElements(); + + SmallVector<Constant*, 16> Idxs; + for (unsigned i = 0; i != NumElts; ++i) { + unsigned Idx = ((Imm >> (i%8)) & 1) ? i + NumElts : i; + Idxs.push_back(Builder.getInt32(Idx)); + } + + Rep = Builder.CreateShuffleVector(Op0, Op1, ConstantVector::get(Idxs)); + } else if (Name == "llvm.x86.avx.vinsertf128.pd.256" || + Name == "llvm.x86.avx.vinsertf128.ps.256" || + Name == "llvm.x86.avx.vinsertf128.si.256" || + Name == "llvm.x86.avx2.vinserti128") { + Value *Op0 = CI->getArgOperand(0); + Value *Op1 = CI->getArgOperand(1); + unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue(); + VectorType *VecTy = cast<VectorType>(CI->getType()); + unsigned NumElts = VecTy->getNumElements(); + + // Mask off the high bits of the immediate value; hardware ignores those. + Imm = Imm & 1; + + // Extend the second operand into a vector that is twice as big. + Value *UndefV = UndefValue::get(Op1->getType()); + SmallVector<Constant*, 8> Idxs; + for (unsigned i = 0; i != NumElts; ++i) { + Idxs.push_back(Builder.getInt32(i)); + } + Rep = Builder.CreateShuffleVector(Op1, UndefV, ConstantVector::get(Idxs)); + + // Insert the second operand into the first operand. + + // Note that there is no guarantee that instruction lowering will actually + // produce a vinsertf128 instruction for the created shuffles. In + // particular, the 0 immediate case involves no lane changes, so it can + // be handled as a blend. + + // Example of shuffle mask for 32-bit elements: + // Imm = 1 <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> + // Imm = 0 <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7 > + + SmallVector<Constant*, 8> Idxs2; + // The low half of the result is either the low half of the 1st operand + // or the low half of the 2nd operand (the inserted vector). + for (unsigned i = 0; i != NumElts / 2; ++i) { + unsigned Idx = Imm ? i : (i + NumElts); + Idxs2.push_back(Builder.getInt32(Idx)); + } + // The high half of the result is either the low half of the 2nd operand + // (the inserted vector) or the high half of the 1st operand. + for (unsigned i = NumElts / 2; i != NumElts; ++i) { + unsigned Idx = Imm ? (i + NumElts / 2) : i; + Idxs2.push_back(Builder.getInt32(Idx)); + } + Rep = Builder.CreateShuffleVector(Op0, Rep, ConstantVector::get(Idxs2)); + } else if (Name == "llvm.x86.avx.vextractf128.pd.256" || + Name == "llvm.x86.avx.vextractf128.ps.256" || + Name == "llvm.x86.avx.vextractf128.si.256" || + Name == "llvm.x86.avx2.vextracti128") { + Value *Op0 = CI->getArgOperand(0); + unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue(); + VectorType *VecTy = cast<VectorType>(CI->getType()); + unsigned NumElts = VecTy->getNumElements(); + + // Mask off the high bits of the immediate value; hardware ignores those. + Imm = Imm & 1; + + // Get indexes for either the high half or low half of the input vector. + SmallVector<Constant*, 4> Idxs(NumElts); + for (unsigned i = 0; i != NumElts; ++i) { + unsigned Idx = Imm ? (i + NumElts) : i; + Idxs[i] = Builder.getInt32(Idx); + } + + Value *UndefV = UndefValue::get(Op0->getType()); + Rep = Builder.CreateShuffleVector(Op0, UndefV, ConstantVector::get(Idxs)); } else { bool PD128 = false, PD256 = false, PS128 = false, PS256 = false; if (Name == "llvm.x86.avx.vpermil.pd.256") @@ -434,7 +618,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { return; } - std::string Name = CI->getName().str(); + std::string Name = CI->getName(); if (!Name.empty()) CI->setName(Name + ".old"); @@ -442,52 +626,31 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { 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 && "Mismatch between function args and call args"); - CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), - Builder.getFalse(), Name)); + CI->replaceAllUsesWith(Builder.CreateCall( + NewFn, {CI->getArgOperand(0), Builder.getFalse()}, Name)); CI->eraseFromParent(); return; case Intrinsic::objectsize: - CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, - CI->getArgOperand(0), - CI->getArgOperand(1), - Name)); + CI->replaceAllUsesWith(Builder.CreateCall( + NewFn, {CI->getArgOperand(0), CI->getArgOperand(1)}, Name)); CI->eraseFromParent(); return; case Intrinsic::ctpop: { - CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0))); + CI->replaceAllUsesWith(Builder.CreateCall(NewFn, {CI->getArgOperand(0)})); CI->eraseFromParent(); return; } case Intrinsic::x86_xop_vfrcz_ss: case Intrinsic::x86_xop_vfrcz_sd: - CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(1), - Name)); + CI->replaceAllUsesWith( + Builder.CreateCall(NewFn, {CI->getArgOperand(1)}, Name)); CI->eraseFromParent(); return; @@ -505,34 +668,22 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { // Old intrinsic, add bitcasts Value *Arg1 = CI->getArgOperand(1); - Value *BC0 = - Builder.CreateBitCast(Arg0, - VectorType::get(Type::getInt64Ty(C), 2), - "cast"); - Value *BC1 = - Builder.CreateBitCast(Arg1, - VectorType::get(Type::getInt64Ty(C), 2), - "cast"); + Type *NewVecTy = VectorType::get(Type::getInt64Ty(C), 2); + + Value *BC0 = Builder.CreateBitCast(Arg0, NewVecTy, "cast"); + Value *BC1 = Builder.CreateBitCast(Arg1, NewVecTy, "cast"); - CallInst* NewCall = Builder.CreateCall2(NewFn, BC0, BC1, Name); + CallInst *NewCall = Builder.CreateCall(NewFn, {BC0, BC1}, Name); CI->replaceAllUsesWith(NewCall); 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. diff --git a/contrib/llvm/lib/IR/BasicBlock.cpp b/contrib/llvm/lib/IR/BasicBlock.cpp index 98a3062..77cb10d 100644 --- a/contrib/llvm/lib/IR/BasicBlock.cpp +++ b/contrib/llvm/lib/IR/BasicBlock.cpp @@ -29,10 +29,6 @@ ValueSymbolTable *BasicBlock::getValueSymbolTable() { return nullptr; } -const DataLayout *BasicBlock::getDataLayout() const { - return getParent()->getDataLayout(); -} - LLVMContext &BasicBlock::getContext() const { return getType()->getContext(); } @@ -98,18 +94,18 @@ void BasicBlock::removeFromParent() { getParent()->getBasicBlockList().remove(this); } -void BasicBlock::eraseFromParent() { - getParent()->getBasicBlockList().erase(this); +iplist<BasicBlock>::iterator BasicBlock::eraseFromParent() { + return getParent()->getBasicBlockList().erase(this); } -/// moveBefore - Unlink this basic block from its current function and +/// Unlink this basic block from its current function and /// insert it into the function that MovePos lives in, right before MovePos. void BasicBlock::moveBefore(BasicBlock *MovePos) { MovePos->getParent()->getBasicBlockList().splice(MovePos, getParent()->getBasicBlockList(), this); } -/// moveAfter - Unlink this basic block from its current function and +/// Unlink this basic block from its current function and /// insert it into the function that MovePos lives in, right after MovePos. void BasicBlock::moveAfter(BasicBlock *MovePos) { Function::iterator I = MovePos; @@ -117,6 +113,13 @@ void BasicBlock::moveAfter(BasicBlock *MovePos) { getParent()->getBasicBlockList(), this); } +const Module *BasicBlock::getModule() const { + return getParent()->getParent(); +} + +Module *BasicBlock::getModule() { + return getParent()->getParent(); +} TerminatorInst *BasicBlock::getTerminator() { if (InstList.empty()) return nullptr; @@ -210,7 +213,7 @@ void BasicBlock::dropAllReferences() { I->dropAllReferences(); } -/// getSinglePredecessor - If this basic block has a single predecessor block, +/// If this basic block has a single predecessor block, /// return the block, otherwise return a null pointer. BasicBlock *BasicBlock::getSinglePredecessor() { pred_iterator PI = pred_begin(this), E = pred_end(this); @@ -220,7 +223,7 @@ BasicBlock *BasicBlock::getSinglePredecessor() { return (PI == E) ? ThePred : nullptr /*multiple preds*/; } -/// getUniquePredecessor - If this basic block has a unique predecessor block, +/// If this basic block has a unique predecessor block, /// return the block, otherwise return a null pointer. /// Note that unique predecessor doesn't mean single edge, there can be /// multiple edges from the unique predecessor to this block (for example @@ -239,7 +242,29 @@ BasicBlock *BasicBlock::getUniquePredecessor() { return PredBB; } -/// removePredecessor - This method is used to notify a BasicBlock that the +BasicBlock *BasicBlock::getSingleSuccessor() { + succ_iterator SI = succ_begin(this), E = succ_end(this); + if (SI == E) return nullptr; // no successors + BasicBlock *TheSucc = *SI; + ++SI; + return (SI == E) ? TheSucc : nullptr /* multiple successors */; +} + +BasicBlock *BasicBlock::getUniqueSuccessor() { + succ_iterator SI = succ_begin(this), E = succ_end(this); + if (SI == E) return NULL; // No successors + BasicBlock *SuccBB = *SI; + ++SI; + for (;SI != E; ++SI) { + if (*SI != SuccBB) + return NULL; + // The same successor appears multiple times in the successor list. + // This is OK. + } + return SuccBB; +} + +/// This method is used to notify a BasicBlock that the /// specified Predecessor of the block is no longer able to reach it. This is /// actually not used to update the Predecessor list, but is actually used to /// update the PHI nodes that reside in the block. Note that this should be @@ -316,7 +341,7 @@ void BasicBlock::removePredecessor(BasicBlock *Pred, } -/// splitBasicBlock - This splits a basic block into two at the specified +/// This splits a basic block into two at the specified /// instruction. Note that all instructions BEFORE the specified iterator stay /// as part of the original basic block, an unconditional branch is added to /// the new BB, and the rest of the instructions in the BB are moved to the new @@ -337,12 +362,15 @@ BasicBlock *BasicBlock::splitBasicBlock(iterator I, const Twine &BBName) { BasicBlock *New = BasicBlock::Create(getContext(), BBName, getParent(), InsertBefore); + // Save DebugLoc of split point before invalidating iterator. + DebugLoc Loc = I->getDebugLoc(); // Move all of the specified instructions from the original basic block into // the new basic block. New->getInstList().splice(New->end(), this->getInstList(), I, end()); // Add a branch instruction to the newly formed basic block. - BranchInst::Create(New, this); + BranchInst *BI = BranchInst::Create(New, this); + BI->setDebugLoc(Loc); // Now we must loop through all of the successors of the New block (which // _were_ the successors of the 'this' block), and update any PHI nodes in @@ -387,14 +415,13 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) { } } -/// isLandingPad - Return true if this basic block is a landing pad. I.e., it's +/// Return true if this basic block is a landing pad. I.e., it's /// the destination of the 'unwind' edge of an invoke instruction. bool BasicBlock::isLandingPad() const { return isa<LandingPadInst>(getFirstNonPHI()); } -/// getLandingPadInst() - Return the landingpad instruction associated with -/// the landing pad. +/// Return the landingpad instruction associated with the landing pad. LandingPadInst *BasicBlock::getLandingPadInst() { return dyn_cast<LandingPadInst>(getFirstNonPHI()); } diff --git a/contrib/llvm/lib/IR/ConstantFold.cpp b/contrib/llvm/lib/IR/ConstantFold.cpp index 39d9a1d..46bb20e 100644 --- a/contrib/llvm/lib/IR/ConstantFold.cpp +++ b/contrib/llvm/lib/IR/ConstantFold.cpp @@ -132,7 +132,8 @@ static Constant *FoldBitCast(Constant *V, Type *DestTy) { if (ElTy == DPTy->getElementType()) // This GEP is inbounds because all indices are zero. - return ConstantExpr::getInBoundsGetElementPtr(V, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(PTy->getElementType(), + V, IdxList); } // Handle casts from one vector constant to another. We know that the src @@ -169,7 +170,8 @@ static Constant *FoldBitCast(Constant *V, Type *DestTy) { // be the same. Consequently, we just fold to V. return V; - if (DestTy->isFloatingPointTy()) + // See note below regarding the PPC_FP128 restriction. + if (DestTy->isFloatingPointTy() && !DestTy->isPPC_FP128Ty()) return ConstantFP::get(DestTy->getContext(), APFloat(DestTy->getFltSemantics(), CI->getValue())); @@ -179,9 +181,19 @@ static Constant *FoldBitCast(Constant *V, Type *DestTy) { } // Handle ConstantFP input: FP -> Integral. - if (ConstantFP *FP = dyn_cast<ConstantFP>(V)) + if (ConstantFP *FP = dyn_cast<ConstantFP>(V)) { + // PPC_FP128 is really the sum of two consecutive doubles, where the first + // double is always stored first in memory, regardless of the target + // endianness. The memory layout of i128, however, depends on the target + // endianness, and so we can't fold this without target endianness + // information. This should instead be handled by + // Analysis/ConstantFolding.cpp + if (FP->getType()->isPPC_FP128Ty()) + return nullptr; + return ConstantInt::get(FP->getContext(), FP->getValueAPF().bitcastToAPInt()); + } return nullptr; } @@ -620,8 +632,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::GetElementPtr && CE->getOperand(0)->isNullValue()) { - Type *Ty = - cast<PointerType>(CE->getOperand(0)->getType())->getElementType(); + GEPOperator *GEPO = cast<GEPOperator>(CE); + Type *Ty = GEPO->getSourceElementType(); if (CE->getNumOperands() == 2) { // Handle a sizeof-like expression. Constant *Idx = CE->getOperand(1); @@ -777,11 +789,10 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val, return UndefValue::get(Val->getType()->getVectorElementType()); if (ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx)) { - uint64_t Index = CIdx->getZExtValue(); // ee({w,x,y,z}, wrong_value) -> undef - if (Index >= Val->getType()->getVectorNumElements()) + if (CIdx->uge(Val->getType()->getVectorNumElements())) return UndefValue::get(Val->getType()->getVectorElementType()); - return Val->getAggregateElement(Index); + return Val->getAggregateElement(CIdx->getZExtValue()); } return nullptr; } @@ -789,23 +800,30 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val, Constant *llvm::ConstantFoldInsertElementInstruction(Constant *Val, Constant *Elt, Constant *Idx) { + if (isa<UndefValue>(Idx)) + return UndefValue::get(Val->getType()); + ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx); if (!CIdx) return nullptr; - const APInt &IdxVal = CIdx->getValue(); - + + unsigned NumElts = Val->getType()->getVectorNumElements(); + if (CIdx->uge(NumElts)) + return UndefValue::get(Val->getType()); + SmallVector<Constant*, 16> Result; - Type *Ty = IntegerType::get(Val->getContext(), 32); - for (unsigned i = 0, e = Val->getType()->getVectorNumElements(); i != e; ++i){ + Result.reserve(NumElts); + auto *Ty = Type::getInt32Ty(Val->getContext()); + uint64_t IdxVal = CIdx->getZExtValue(); + for (unsigned i = 0; i != NumElts; ++i) { if (i == IdxVal) { Result.push_back(Elt); continue; } - Constant *C = - ConstantExpr::getExtractElement(Val, ConstantInt::get(Ty, i)); + Constant *C = ConstantExpr::getExtractElement(Val, ConstantInt::get(Ty, i)); Result.push_back(C); } - + return ConstantVector::get(Result); } @@ -1273,15 +1291,17 @@ static int IdxCompare(Constant *C1, Constant *C2, Type *ElTy) { if (!isa<ConstantInt>(C1) || !isa<ConstantInt>(C2)) return -2; // don't know! - // Ok, we have two differing integer indices. Sign extend them to be the same - // type. Long is always big enough, so we use it. - if (!C1->getType()->isIntegerTy(64)) - C1 = ConstantExpr::getSExt(C1, Type::getInt64Ty(C1->getContext())); + // We cannot compare the indices if they don't fit in an int64_t. + if (cast<ConstantInt>(C1)->getValue().getActiveBits() > 64 || + cast<ConstantInt>(C2)->getValue().getActiveBits() > 64) + return -2; // don't know! - if (!C2->getType()->isIntegerTy(64)) - C2 = ConstantExpr::getSExt(C2, Type::getInt64Ty(C1->getContext())); + // Ok, we have two differing integer indices. Sign extend them to be the same + // type. + int64_t C1Val = cast<ConstantInt>(C1)->getSExtValue(); + int64_t C2Val = cast<ConstantInt>(C2)->getSExtValue(); - if (C1 == C2) return 0; // They are equal + if (C1Val == C2Val) return 0; // They are equal // If the type being indexed over is really just a zero sized type, there is // no pointer difference being made here. @@ -1290,8 +1310,7 @@ static int IdxCompare(Constant *C1, Constant *C2, Type *ElTy) { // If they are really different, now that they are the same type, then we // found a difference! - if (cast<ConstantInt>(C1)->getSExtValue() < - cast<ConstantInt>(C2)->getSExtValue()) + if (C1Val < C2Val) return -1; else return 1; @@ -1317,7 +1336,7 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) { if (!isa<ConstantExpr>(V1)) { if (!isa<ConstantExpr>(V2)) { - // We distilled thisUse the standard constant folder for a few cases + // Simple case, use the standard constant folder. ConstantInt *R = nullptr; R = dyn_cast<ConstantInt>( ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ, V1, V2)); @@ -1366,7 +1385,7 @@ static ICmpInst::Predicate areGlobalsPotentiallyEqual(const GlobalValue *GV1, if (GV->hasExternalWeakLinkage() || GV->hasWeakAnyLinkage()) return true; if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) { - Type *Ty = GVar->getType()->getPointerElementType(); + Type *Ty = GVar->getValueType(); // A global with opaque type might end up being zero sized. if (!Ty->isSized()) return true; @@ -1655,15 +1674,22 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, // Handle some degenerate cases first if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) { + CmpInst::Predicate Predicate = CmpInst::Predicate(pred); + bool isIntegerPredicate = ICmpInst::isIntPredicate(Predicate); // For EQ and NE, we can always pick a value for the undef to make the // predicate pass or fail, so we can return undef. - // Also, if both operands are undef, we can return undef. - if (ICmpInst::isEquality(ICmpInst::Predicate(pred)) || - (isa<UndefValue>(C1) && isa<UndefValue>(C2))) + // Also, if both operands are undef, we can return undef for int comparison. + if (ICmpInst::isEquality(Predicate) || (isIntegerPredicate && C1 == C2)) return UndefValue::get(ResultTy); - // Otherwise, pick the same value as the non-undef operand, and fold - // it to true or false. - return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred)); + + // Otherwise, for integer compare, pick the same value as the non-undef + // operand, and fold it to true or false. + if (isIntegerPredicate) + return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred)); + + // Choosing NaN for the undef will always make unordered comparison succeed + // and ordered comparison fails. + return ConstantInt::get(ResultTy, CmpInst::isUnordered(Predicate)); } // icmp eq/ne(null,GV) -> false/true @@ -1779,7 +1805,10 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, return ConstantVector::get(ResElts); } - if (C1->getType()->isFloatingPointTy()) { + if (C1->getType()->isFloatingPointTy() && + // Only call evaluateFCmpRelation if we have a constant expr to avoid + // infinite recursive loop + (isa<ConstantExpr>(C1) || isa<ConstantExpr>(C2))) { int Result = -1; // -1 = unknown, 0 = known false, 1 = known true. switch (evaluateFCmpRelation(C1, C2)) { default: llvm_unreachable("Unknown relation!"); @@ -1999,7 +2028,7 @@ static bool isIndexInRangeOfSequentialType(const SequentialType *STy, } template<typename IndexTy> -static Constant *ConstantFoldGetElementPtrImpl(Constant *C, +static Constant *ConstantFoldGetElementPtrImpl(Type *PointeeTy, Constant *C, bool inBounds, ArrayRef<IndexTy> Idxs) { if (Idxs.empty()) return C; @@ -2009,7 +2038,8 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, if (isa<UndefValue>(C)) { PointerType *Ptr = cast<PointerType>(C->getType()); - Type *Ty = GetElementPtrInst::getIndexedType(Ptr, Idxs); + Type *Ty = GetElementPtrInst::getIndexedType( + cast<PointerType>(Ptr->getScalarType())->getElementType(), Idxs); assert(Ty && "Invalid indices for GEP!"); return UndefValue::get(PointerType::get(Ty, Ptr->getAddressSpace())); } @@ -2023,7 +2053,8 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, } if (isNull) { PointerType *Ptr = cast<PointerType>(C->getType()); - Type *Ty = GetElementPtrInst::getIndexedType(Ptr, Idxs); + Type *Ty = GetElementPtrInst::getIndexedType( + cast<PointerType>(Ptr->getScalarType())->getElementType(), Idxs); assert(Ty && "Invalid indices for GEP!"); return ConstantPointerNull::get(PointerType::get(Ty, Ptr->getAddressSpace())); @@ -2069,8 +2100,7 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, if (PerformFold) { SmallVector<Value*, 16> NewIndices; NewIndices.reserve(Idxs.size() + CE->getNumOperands()); - for (unsigned i = 1, e = CE->getNumOperands()-1; i != e; ++i) - NewIndices.push_back(CE->getOperand(i)); + NewIndices.append(CE->op_begin() + 1, CE->op_end() - 1); // Add the last index of the source with the first index of the new GEP. // Make sure to handle the case when they are actually different types. @@ -2079,9 +2109,15 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, if (!Idx0->isNullValue()) { Type *IdxTy = Combined->getType(); if (IdxTy != Idx0->getType()) { - Type *Int64Ty = Type::getInt64Ty(IdxTy->getContext()); - Constant *C1 = ConstantExpr::getSExtOrBitCast(Idx0, Int64Ty); - Constant *C2 = ConstantExpr::getSExtOrBitCast(Combined, Int64Ty); + unsigned CommonExtendedWidth = + std::max(IdxTy->getIntegerBitWidth(), + Idx0->getType()->getIntegerBitWidth()); + CommonExtendedWidth = std::max(CommonExtendedWidth, 64U); + + Type *CommonTy = + Type::getIntNTy(IdxTy->getContext(), CommonExtendedWidth); + Constant *C1 = ConstantExpr::getSExtOrBitCast(Idx0, CommonTy); + Constant *C2 = ConstantExpr::getSExtOrBitCast(Combined, CommonTy); Combined = ConstantExpr::get(Instruction::Add, C1, C2); } else { Combined = @@ -2091,10 +2127,9 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, NewIndices.push_back(Combined); NewIndices.append(Idxs.begin() + 1, Idxs.end()); - return - ConstantExpr::getGetElementPtr(CE->getOperand(0), NewIndices, - inBounds && - cast<GEPOperator>(CE)->isInBounds()); + return ConstantExpr::getGetElementPtr( + cast<GEPOperator>(CE)->getSourceElementType(), CE->getOperand(0), + NewIndices, inBounds && cast<GEPOperator>(CE)->isInBounds()); } } @@ -2119,8 +2154,8 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, if (SrcArrayTy && DstArrayTy && SrcArrayTy->getElementType() == DstArrayTy->getElementType() && SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace()) - return ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0), - Idxs, inBounds); + return ConstantExpr::getGetElementPtr( + SrcArrayTy, (Constant *)CE->getOperand(0), Idxs, inBounds); } } } @@ -2128,11 +2163,11 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, // Check to see if any array indices are not within the corresponding // notional array or vector bounds. If so, try to determine if they can be // factored out into preceding dimensions. - bool Unknown = false; SmallVector<Constant *, 8> NewIdxs; - Type *Ty = C->getType(); - Type *Prev = nullptr; - for (unsigned i = 0, e = Idxs.size(); i != e; + Type *Ty = PointeeTy; + Type *Prev = C->getType(); + bool Unknown = !isa<ConstantInt>(Idxs[0]); + for (unsigned i = 1, e = Idxs.size(); i != e; Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) { if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) { if (isa<ArrayType>(Ty) || isa<VectorType>(Ty)) @@ -2154,14 +2189,20 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, Constant *PrevIdx = cast<Constant>(Idxs[i-1]); Constant *Div = ConstantExpr::getSDiv(CI, Factor); + unsigned CommonExtendedWidth = + std::max(PrevIdx->getType()->getIntegerBitWidth(), + Div->getType()->getIntegerBitWidth()); + CommonExtendedWidth = std::max(CommonExtendedWidth, 64U); + // Before adding, extend both operands to i64 to avoid // overflow trouble. - if (!PrevIdx->getType()->isIntegerTy(64)) - PrevIdx = ConstantExpr::getSExt(PrevIdx, - Type::getInt64Ty(Div->getContext())); - if (!Div->getType()->isIntegerTy(64)) - Div = ConstantExpr::getSExt(Div, - Type::getInt64Ty(Div->getContext())); + if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth)) + PrevIdx = ConstantExpr::getSExt( + PrevIdx, + Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); + if (!Div->getType()->isIntegerTy(CommonExtendedWidth)) + Div = ConstantExpr::getSExt( + Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); NewIdxs[i-1] = ConstantExpr::getAdd(PrevIdx, Div); } else { @@ -2180,7 +2221,7 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, if (!NewIdxs.empty()) { for (unsigned i = 0, e = Idxs.size(); i != e; ++i) if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]); - return ConstantExpr::getGetElementPtr(C, NewIdxs, inBounds); + return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, inBounds); } // If all indices are known integers and normalized, we can do a simple @@ -2188,7 +2229,7 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, if (!Unknown && !inBounds) if (auto *GV = dyn_cast<GlobalVariable>(C)) if (!GV->hasExternalWeakLinkage() && isInBoundsIndices(Idxs)) - return ConstantExpr::getInBoundsGetElementPtr(C, Idxs); + return ConstantExpr::getInBoundsGetElementPtr(PointeeTy, C, Idxs); return nullptr; } @@ -2196,11 +2237,27 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, Constant *llvm::ConstantFoldGetElementPtr(Constant *C, bool inBounds, ArrayRef<Constant *> Idxs) { - return ConstantFoldGetElementPtrImpl(C, inBounds, Idxs); + return ConstantFoldGetElementPtrImpl( + cast<PointerType>(C->getType()->getScalarType())->getElementType(), C, + inBounds, Idxs); } Constant *llvm::ConstantFoldGetElementPtr(Constant *C, bool inBounds, ArrayRef<Value *> Idxs) { - return ConstantFoldGetElementPtrImpl(C, inBounds, Idxs); + return ConstantFoldGetElementPtrImpl( + cast<PointerType>(C->getType()->getScalarType())->getElementType(), C, + inBounds, Idxs); +} + +Constant *llvm::ConstantFoldGetElementPtr(Type *Ty, Constant *C, + bool inBounds, + ArrayRef<Constant *> Idxs) { + return ConstantFoldGetElementPtrImpl(Ty, C, inBounds, Idxs); +} + +Constant *llvm::ConstantFoldGetElementPtr(Type *Ty, Constant *C, + bool inBounds, + ArrayRef<Value *> Idxs) { + return ConstantFoldGetElementPtrImpl(Ty, C, inBounds, Idxs); } diff --git a/contrib/llvm/lib/IR/ConstantFold.h b/contrib/llvm/lib/IR/ConstantFold.h index a516abe..715c429 100644 --- a/contrib/llvm/lib/IR/ConstantFold.h +++ b/contrib/llvm/lib/IR/ConstantFold.h @@ -51,6 +51,10 @@ namespace llvm { ArrayRef<Constant *> Idxs); Constant *ConstantFoldGetElementPtr(Constant *C, bool inBounds, ArrayRef<Value *> Idxs); -} // End llvm namespace + Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds, + ArrayRef<Constant *> Idxs); + Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds, + ArrayRef<Value *> Idxs); +} // namespace llvm #endif diff --git a/contrib/llvm/lib/IR/ConstantRange.cpp b/contrib/llvm/lib/IR/ConstantRange.cpp index f8e9ba4..91095cf 100644 --- a/contrib/llvm/lib/IR/ConstantRange.cpp +++ b/contrib/llvm/lib/IR/ConstantRange.cpp @@ -49,14 +49,15 @@ ConstantRange::ConstantRange(APIntMoveTy L, APIntMoveTy U) "Lower == Upper, but they aren't min or max value!"); } -ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, - const ConstantRange &CR) { +ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &CR) { if (CR.isEmptySet()) return CR; uint32_t W = CR.getBitWidth(); switch (Pred) { - default: llvm_unreachable("Invalid ICmp predicate to makeICmpRegion()"); + default: + llvm_unreachable("Invalid ICmp predicate to makeAllowedICmpRegion()"); case CmpInst::ICMP_EQ: return CR; case CmpInst::ICMP_NE: @@ -114,6 +115,16 @@ ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, } } +ConstantRange ConstantRange::makeSatisfyingICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &CR) { + // Follows from De-Morgan's laws: + // + // ~(~A union ~B) == A intersect B. + // + return makeAllowedICmpRegion(CmpInst::getInversePredicate(Pred), CR) + .inverse(); +} + /// isFullSet - Return true if this set contains all of the elements possible /// for this data-type bool ConstantRange::isFullSet() const { @@ -587,6 +598,13 @@ ConstantRange::multiply(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); + // Multiplication is signedness-independent. However different ranges can be + // obtained depending on how the input ranges are treated. These different + // ranges are all conservatively correct, but one might be better than the + // other. We calculate two ranges; one treating the inputs as unsigned + // and the other signed, then return the smallest of these ranges. + + // Unsigned range first. APInt this_min = getUnsignedMin().zext(getBitWidth() * 2); APInt this_max = getUnsignedMax().zext(getBitWidth() * 2); APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2); @@ -594,7 +612,26 @@ ConstantRange::multiply(const ConstantRange &Other) const { ConstantRange Result_zext = ConstantRange(this_min * Other_min, this_max * Other_max + 1); - return Result_zext.truncate(getBitWidth()); + ConstantRange UR = Result_zext.truncate(getBitWidth()); + + // Now the signed range. Because we could be dealing with negative numbers + // here, the lower bound is the smallest of the cartesian product of the + // lower and upper ranges; for example: + // [-1,4) * [-2,3) = min(-1*-2, -1*2, 3*-2, 3*2) = -6. + // Similarly for the upper bound, swapping min for max. + + this_min = getSignedMin().sext(getBitWidth() * 2); + this_max = getSignedMax().sext(getBitWidth() * 2); + Other_min = Other.getSignedMin().sext(getBitWidth() * 2); + Other_max = Other.getSignedMax().sext(getBitWidth() * 2); + + auto L = {this_min * Other_min, this_min * Other_max, + this_max * Other_min, this_max * Other_max}; + auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); }; + ConstantRange Result_sext(std::min(L, Compare), std::max(L, Compare) + 1); + ConstantRange SR = Result_sext.truncate(getBitWidth()); + + return UR.getSetSize().ult(SR.getSetSize()) ? UR : SR; } ConstantRange diff --git a/contrib/llvm/lib/IR/Constants.cpp b/contrib/llvm/lib/IR/Constants.cpp index 44052b2..76c55b6 100644 --- a/contrib/llvm/lib/IR/Constants.cpp +++ b/contrib/llvm/lib/IR/Constants.cpp @@ -663,6 +663,17 @@ Constant *ConstantFP::get(Type *Ty, StringRef Str) { return C; } +Constant *ConstantFP::getNaN(Type *Ty, bool Negative, unsigned Type) { + const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType()); + APFloat NaN = APFloat::getNaN(Semantics, Negative, Type); + Constant *C = get(Ty->getContext(), NaN); + + if (VectorType *VTy = dyn_cast<VectorType>(Ty)) + return ConstantVector::getSplat(VTy->getNumElements(), C); + + return C; +} + Constant *ConstantFP::getNegativeZero(Type *Ty) { const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType()); APFloat NegZero = APFloat::getZero(Semantics, /*Negative=*/true); @@ -911,23 +922,25 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) { if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { if (CFP->getType()->isFloatTy()) { - SmallVector<float, 16> Elts; + SmallVector<uint32_t, 16> Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) - Elts.push_back(CFP->getValueAPF().convertToFloat()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); + return ConstantDataArray::getFP(C->getContext(), Elts); } else if (CFP->getType()->isDoubleTy()) { - SmallVector<double, 16> Elts; + SmallVector<uint64_t, 16> Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) - Elts.push_back(CFP->getValueAPF().convertToDouble()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataArray::get(C->getContext(), Elts); + return ConstantDataArray::getFP(C->getContext(), Elts); } } } @@ -1097,23 +1110,25 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) { if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { if (CFP->getType()->isFloatTy()) { - SmallVector<float, 16> Elts; + SmallVector<uint32_t, 16> Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) - Elts.push_back(CFP->getValueAPF().convertToFloat()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataVector::get(C->getContext(), Elts); + return ConstantDataVector::getFP(C->getContext(), Elts); } else if (CFP->getType()->isDoubleTy()) { - SmallVector<double, 16> Elts; + SmallVector<uint64_t, 16> Elts; for (unsigned i = 0, e = V.size(); i != e; ++i) if (ConstantFP *CFP = dyn_cast<ConstantFP>(V[i])) - Elts.push_back(CFP->getValueAPF().convertToDouble()); + Elts.push_back( + CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); else break; if (Elts.size() == V.size()) - return ConstantDataVector::get(C->getContext(), Elts); + return ConstantDataVector::getFP(C->getContext(), Elts); } } } @@ -1211,11 +1226,9 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) 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) - AnyChange |= Ops[i] != getOperand(i); - if (!AnyChange) // No operands changed, return self. + // If no operands changed return self. + if (Ty == getType() && std::equal(Ops.begin(), Ops.end(), op_begin())) return const_cast<ConstantExpr*>(this); Type *OnlyIfReducedTy = OnlyIfReduced ? Ty : nullptr; @@ -1250,7 +1263,7 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2], OnlyIfReducedTy); case Instruction::GetElementPtr: - return ConstantExpr::getGetElementPtr(Ops[0], Ops.slice(1), + return ConstantExpr::getGetElementPtr(nullptr, Ops[0], Ops.slice(1), cast<GEPOperator>(this)->isInBounds(), OnlyIfReducedTy); case Instruction::ICmp: @@ -1923,7 +1936,7 @@ Constant *ConstantExpr::getSizeOf(Type* Ty) { // Note that a non-inbounds gep is used, as null isn't within any object. Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1); Constant *GEP = getGetElementPtr( - Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx); + Ty, Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx); return getPtrToInt(GEP, Type::getInt64Ty(Ty->getContext())); } @@ -1937,7 +1950,7 @@ Constant *ConstantExpr::getAlignOf(Type* Ty) { Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0); Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1); Constant *Indices[2] = { Zero, One }; - Constant *GEP = getGetElementPtr(NullPtr, Indices); + Constant *GEP = getGetElementPtr(AligningTy, NullPtr, Indices); return getPtrToInt(GEP, Type::getInt64Ty(Ty->getContext())); } @@ -1955,7 +1968,7 @@ Constant *ConstantExpr::getOffsetOf(Type* Ty, Constant *FieldNo) { FieldNo }; Constant *GEP = getGetElementPtr( - Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx); + Ty, Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx); return getPtrToInt(GEP, Type::getInt64Ty(Ty->getContext())); } @@ -1999,19 +2012,24 @@ Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2, return pImpl->ExprConstants.getOrCreate(V1->getType(), Key); } -Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, - bool InBounds, Type *OnlyIfReducedTy) { - assert(C->getType()->isPtrOrPtrVectorTy() && - "Non-pointer type for constant GetElementPtr expression"); +Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> Idxs, bool InBounds, + Type *OnlyIfReducedTy) { + if (!Ty) + Ty = cast<PointerType>(C->getType()->getScalarType())->getElementType(); + else + assert( + Ty == + cast<PointerType>(C->getType()->getScalarType())->getContainedType(0u)); - if (Constant *FC = ConstantFoldGetElementPtr(C, InBounds, Idxs)) + if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, Idxs)) return FC; // Fold a few common cases. // Get the result type of the getelementptr! - Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), Idxs); - assert(Ty && "GEP indices invalid!"); + Type *DestTy = GetElementPtrInst::getIndexedType(Ty, Idxs); + assert(DestTy && "GEP indices invalid!"); unsigned AS = C->getType()->getPointerAddressSpace(); - Type *ReqTy = Ty->getPointerTo(AS); + Type *ReqTy = DestTy->getPointerTo(AS); if (VectorType *VecTy = dyn_cast<VectorType>(C->getType())) ReqTy = VectorType::get(ReqTy, VecTy->getNumElements()); @@ -2032,7 +2050,8 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, ArgVec.push_back(cast<Constant>(Idxs[i])); } const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0, - InBounds ? GEPOperator::IsInBounds : 0); + InBounds ? GEPOperator::IsInBounds : 0, None, + Ty); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -2362,19 +2381,23 @@ const char *ConstantExpr::getOpcodeName() const { return Instruction::getOpcodeName(getOpcode()); } - - -GetElementPtrConstantExpr:: -GetElementPtrConstantExpr(Constant *C, ArrayRef<Constant*> IdxList, - Type *DestTy) - : ConstantExpr(DestTy, Instruction::GetElementPtr, - OperandTraits<GetElementPtrConstantExpr>::op_end(this) - - (IdxList.size()+1), IdxList.size()+1) { - OperandList[0] = C; +GetElementPtrConstantExpr::GetElementPtrConstantExpr( + Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, Type *DestTy) + : ConstantExpr(DestTy, Instruction::GetElementPtr, + OperandTraits<GetElementPtrConstantExpr>::op_end(this) - + (IdxList.size() + 1), + IdxList.size() + 1), + SrcElementTy(SrcElementTy) { + Op<0>() = C; + Use *OperandList = getOperandList(); for (unsigned i = 0, E = IdxList.size(); i != E; ++i) OperandList[i+1] = IdxList[i]; } +Type *GetElementPtrConstantExpr::getSourceElementType() const { + return SrcElementTy; +} + //===----------------------------------------------------------------------===// // ConstantData* implementations @@ -2544,7 +2567,31 @@ Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<float> Elts) { Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<double> Elts) { Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size()); const char *Data = reinterpret_cast<const char *>(Elts.data()); - return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty); +} + +/// getFP() constructors - Return a constant with array type with an element +/// count and element type of float with precision matching the number of +/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, +/// double for 64bits) Note that this can return a ConstantAggregateZero +/// object. +Constant *ConstantDataArray::getFP(LLVMContext &Context, + ArrayRef<uint16_t> Elts) { + Type *Ty = VectorType::get(Type::getHalfTy(Context), Elts.size()); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 2), Ty); +} +Constant *ConstantDataArray::getFP(LLVMContext &Context, + ArrayRef<uint32_t> Elts) { + Type *Ty = ArrayType::get(Type::getFloatTy(Context), Elts.size()); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 4), Ty); +} +Constant *ConstantDataArray::getFP(LLVMContext &Context, + ArrayRef<uint64_t> Elts) { + Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size()); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty); } /// getString - This method constructs a CDS and initializes it with a text @@ -2597,7 +2644,31 @@ Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<float> Elts) { Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<double> Elts) { Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size()); const char *Data = reinterpret_cast<const char *>(Elts.data()); - return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty); +} + +/// getFP() constructors - Return a constant with vector type with an element +/// count and element type of float with the precision matching the number of +/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, +/// double for 64bits) Note that this can return a ConstantAggregateZero +/// object. +Constant *ConstantDataVector::getFP(LLVMContext &Context, + ArrayRef<uint16_t> Elts) { + Type *Ty = VectorType::get(Type::getHalfTy(Context), Elts.size()); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 2), Ty); +} +Constant *ConstantDataVector::getFP(LLVMContext &Context, + ArrayRef<uint32_t> Elts) { + Type *Ty = VectorType::get(Type::getFloatTy(Context), Elts.size()); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 4), Ty); +} +Constant *ConstantDataVector::getFP(LLVMContext &Context, + ArrayRef<uint64_t> Elts) { + Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size()); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size() * 8), Ty); } Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) { @@ -2623,13 +2694,14 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) { if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) { if (CFP->getType()->isFloatTy()) { - SmallVector<float, 16> Elts(NumElts, CFP->getValueAPF().convertToFloat()); - return get(V->getContext(), Elts); + SmallVector<uint32_t, 16> Elts( + NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); + return getFP(V->getContext(), Elts); } if (CFP->getType()->isDoubleTy()) { - SmallVector<double, 16> Elts(NumElts, - CFP->getValueAPF().convertToDouble()); - return get(V->getContext(), Elts); + SmallVector<uint64_t, 16> Elts( + NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); + return getFP(V->getContext(), Elts); } } return ConstantVector::getSplat(NumElts, V); @@ -2667,13 +2739,13 @@ APFloat ConstantDataSequential::getElementAsAPFloat(unsigned Elt) const { default: llvm_unreachable("Accessor can only be used when element is float/double!"); case Type::FloatTyID: { - const float *FloatPrt = reinterpret_cast<const float *>(EltPtr); - return APFloat(*const_cast<float *>(FloatPrt)); - } + auto EltVal = *reinterpret_cast<const uint32_t *>(EltPtr); + return APFloat(APFloat::IEEEsingle, APInt(32, EltVal)); + } case Type::DoubleTyID: { - const double *DoublePtr = reinterpret_cast<const double *>(EltPtr); - return APFloat(*const_cast<double *>(DoublePtr)); - } + auto EltVal = *reinterpret_cast<const uint64_t *>(EltPtr); + return APFloat(APFloat::IEEEdouble, APInt(64, EltVal)); + } } } @@ -2780,6 +2852,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, // Keep track of whether all the values in the array are "ToC". bool AllSame = true; + Use *OperandList = getOperandList(); for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { Constant *Val = cast<Constant>(O->get()); if (Val == From) { @@ -2816,6 +2889,7 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast<Constant>(To); + Use *OperandList = getOperandList(); unsigned OperandToUpdate = U-OperandList; assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); @@ -2884,6 +2958,7 @@ void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, } // Update to the new value. + Use *OperandList = getOperandList(); if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace( Values, this, From, ToC, NumUpdated, U - OperandList)) replaceUsesOfWithOnConstantImpl(C); @@ -2912,16 +2987,14 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, } // Update to the new value. + Use *OperandList = getOperandList(); if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace( NewOps, this, From, To, NumUpdated, U - OperandList)) replaceUsesOfWithOnConstantImpl(C); } Instruction *ConstantExpr::getAsInstruction() { - SmallVector<Value*,4> ValueOperands; - for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) - ValueOperands.push_back(cast<Value>(I)); - + SmallVector<Value *, 4> ValueOperands(op_begin(), op_end()); ArrayRef<Value*> Ops(ValueOperands); switch (getOpcode()) { @@ -2953,12 +3026,14 @@ Instruction *ConstantExpr::getAsInstruction() { case Instruction::ShuffleVector: return new ShuffleVectorInst(Ops[0], Ops[1], Ops[2]); - case Instruction::GetElementPtr: - if (cast<GEPOperator>(this)->isInBounds()) - return GetElementPtrInst::CreateInBounds(Ops[0], Ops.slice(1)); - else - return GetElementPtrInst::Create(Ops[0], Ops.slice(1)); - + case Instruction::GetElementPtr: { + const auto *GO = cast<GEPOperator>(this); + if (GO->isInBounds()) + return GetElementPtrInst::CreateInBounds(GO->getSourceElementType(), + Ops[0], Ops.slice(1)); + return GetElementPtrInst::Create(GO->getSourceElementType(), Ops[0], + Ops.slice(1)); + } case Instruction::ICmp: case Instruction::FCmp: return CmpInst::Create((Instruction::OtherOps)getOpcode(), diff --git a/contrib/llvm/lib/IR/ConstantsContext.h b/contrib/llvm/lib/IR/ConstantsContext.h index 571dec2..f3ddcd7 100644 --- a/contrib/llvm/lib/IR/ConstantsContext.h +++ b/contrib/llvm/lib/IR/ConstantsContext.h @@ -34,7 +34,7 @@ namespace llvm { /// behind the scenes to implement unary constant exprs. class UnaryConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly one operand void *operator new(size_t s) { @@ -51,7 +51,7 @@ public: /// behind the scenes to implement binary constant exprs. class BinaryConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -72,7 +72,7 @@ public: /// behind the scenes to implement select constant exprs. class SelectConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly three operands void *operator new(size_t s) { @@ -93,14 +93,14 @@ public: /// extractelement constant exprs. class ExtractElementConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly two operands void *operator new(size_t s) { return User::operator new(s, 2); } ExtractElementConstantExpr(Constant *C1, Constant *C2) - : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(), + : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(), Instruction::ExtractElement, &Op<0>(), 2) { Op<0>() = C1; Op<1>() = C2; @@ -114,14 +114,14 @@ public: /// insertelement constant exprs. class InsertElementConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly three operands void *operator new(size_t s) { return User::operator new(s, 3); } InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3) - : ConstantExpr(C1->getType(), Instruction::InsertElement, + : ConstantExpr(C1->getType(), Instruction::InsertElement, &Op<0>(), 3) { Op<0>() = C1; Op<1>() = C2; @@ -136,7 +136,7 @@ public: /// shufflevector constant exprs. class ShuffleVectorConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly three operands void *operator new(size_t s) { @@ -146,7 +146,7 @@ public: : ConstantExpr(VectorType::get( cast<VectorType>(C1->getType())->getElementType(), cast<VectorType>(C3->getType())->getNumElements()), - Instruction::ShuffleVector, + Instruction::ShuffleVector, &Op<0>(), 3) { Op<0>() = C1; Op<1>() = C2; @@ -161,7 +161,7 @@ public: /// extractvalue constant exprs. class ExtractValueConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly one operand void *operator new(size_t s) { @@ -186,7 +186,7 @@ public: /// insertvalue constant exprs. class InsertValueConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly one operand void *operator new(size_t s) { @@ -207,23 +207,32 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; - /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is /// used behind the scenes to implement getelementpr constant exprs. class GetElementPtrConstantExpr : public ConstantExpr { + Type *SrcElementTy; void anchor() override; - GetElementPtrConstantExpr(Constant *C, ArrayRef<Constant*> IdxList, - Type *DestTy); + GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C, + ArrayRef<Constant *> IdxList, Type *DestTy); + public: static GetElementPtrConstantExpr *Create(Constant *C, ArrayRef<Constant*> IdxList, Type *DestTy, unsigned Flags) { - GetElementPtrConstantExpr *Result = - new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy); + return Create( + cast<PointerType>(C->getType()->getScalarType())->getElementType(), C, + IdxList, DestTy, Flags); + } + static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C, + ArrayRef<Constant *> IdxList, + Type *DestTy, unsigned Flags) { + GetElementPtrConstantExpr *Result = new (IdxList.size() + 1) + GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy); Result->SubclassOptionalData = Flags; return Result; } + Type *getSourceElementType() const; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -233,7 +242,7 @@ public: // needed in order to store the predicate value for these instructions. class CompareConstantExpr : public ConstantExpr { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -251,65 +260,54 @@ public: }; template <> -struct OperandTraits<UnaryConstantExpr> : - public FixedNumOperandTraits<UnaryConstantExpr, 1> { -}; +struct OperandTraits<UnaryConstantExpr> + : public FixedNumOperandTraits<UnaryConstantExpr, 1> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr, Value) template <> -struct OperandTraits<BinaryConstantExpr> : - public FixedNumOperandTraits<BinaryConstantExpr, 2> { -}; +struct OperandTraits<BinaryConstantExpr> + : public FixedNumOperandTraits<BinaryConstantExpr, 2> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value) template <> -struct OperandTraits<SelectConstantExpr> : - public FixedNumOperandTraits<SelectConstantExpr, 3> { -}; +struct OperandTraits<SelectConstantExpr> + : public FixedNumOperandTraits<SelectConstantExpr, 3> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, Value) template <> -struct OperandTraits<ExtractElementConstantExpr> : - public FixedNumOperandTraits<ExtractElementConstantExpr, 2> { -}; +struct OperandTraits<ExtractElementConstantExpr> + : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value) template <> -struct OperandTraits<InsertElementConstantExpr> : - public FixedNumOperandTraits<InsertElementConstantExpr, 3> { -}; +struct OperandTraits<InsertElementConstantExpr> + : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value) template <> -struct OperandTraits<ShuffleVectorConstantExpr> : - public FixedNumOperandTraits<ShuffleVectorConstantExpr, 3> { -}; +struct OperandTraits<ShuffleVectorConstantExpr> + : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 3> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value) template <> -struct OperandTraits<ExtractValueConstantExpr> : - public FixedNumOperandTraits<ExtractValueConstantExpr, 1> { -}; +struct OperandTraits<ExtractValueConstantExpr> + : public FixedNumOperandTraits<ExtractValueConstantExpr, 1> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value) template <> -struct OperandTraits<InsertValueConstantExpr> : - public FixedNumOperandTraits<InsertValueConstantExpr, 2> { -}; +struct OperandTraits<InsertValueConstantExpr> + : public FixedNumOperandTraits<InsertValueConstantExpr, 2> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value) template <> -struct OperandTraits<GetElementPtrConstantExpr> : - public VariadicOperandTraits<GetElementPtrConstantExpr, 1> { -}; +struct OperandTraits<GetElementPtrConstantExpr> + : public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value) - template <> -struct OperandTraits<CompareConstantExpr> : - public FixedNumOperandTraits<CompareConstantExpr, 2> { -}; +struct OperandTraits<CompareConstantExpr> + : public FixedNumOperandTraits<CompareConstantExpr, 2> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) template <class ConstantClass> struct ConstantAggrKeyType; @@ -420,13 +418,16 @@ struct ConstantExprKeyType { uint16_t SubclassData; ArrayRef<Constant *> Ops; ArrayRef<unsigned> Indexes; + Type *ExplicitTy; ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops, unsigned short SubclassData = 0, unsigned short SubclassOptionalData = 0, - ArrayRef<unsigned> Indexes = None) + ArrayRef<unsigned> Indexes = None, + Type *ExplicitTy = nullptr) : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), - SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {} + SubclassData(SubclassData), Ops(Ops), Indexes(Indexes), + ExplicitTy(ExplicitTy) {} ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE) : Opcode(CE->getOpcode()), SubclassOptionalData(CE->getRawSubclassOptionalData()), @@ -497,8 +498,11 @@ struct ConstantExprKeyType { case Instruction::ExtractValue: return new ExtractValueConstantExpr(Ops[0], Indexes, Ty); case Instruction::GetElementPtr: - return GetElementPtrConstantExpr::Create(Ops[0], Ops.slice(1), Ty, - SubclassOptionalData); + return GetElementPtrConstantExpr::Create( + ExplicitTy ? ExplicitTy + : cast<PointerType>(Ops[0]->getType()->getScalarType()) + ->getElementType(), + Ops[0], Ops.slice(1), Ty, SubclassOptionalData); case Instruction::ICmp: return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData, Ops[0], Ops[1]); diff --git a/contrib/llvm/lib/IR/Core.cpp b/contrib/llvm/lib/IR/Core.cpp index 753d9c2..23e923d 100644 --- a/contrib/llvm/lib/IR/Core.cpp +++ b/contrib/llvm/lib/IR/Core.cpp @@ -26,8 +26,8 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -310,6 +310,9 @@ LLVMTypeRef LLVMInt32TypeInContext(LLVMContextRef C) { LLVMTypeRef LLVMInt64TypeInContext(LLVMContextRef C) { return (LLVMTypeRef) Type::getInt64Ty(*unwrap(C)); } +LLVMTypeRef LLVMInt128TypeInContext(LLVMContextRef C) { + return (LLVMTypeRef) Type::getInt128Ty(*unwrap(C)); +} LLVMTypeRef LLVMIntTypeInContext(LLVMContextRef C, unsigned NumBits) { return wrap(IntegerType::get(*unwrap(C), NumBits)); } @@ -329,6 +332,9 @@ LLVMTypeRef LLVMInt32Type(void) { LLVMTypeRef LLVMInt64Type(void) { return LLVMInt64TypeInContext(LLVMGetGlobalContext()); } +LLVMTypeRef LLVMInt128Type(void) { + return LLVMInt128TypeInContext(LLVMGetGlobalContext()); +} LLVMTypeRef LLVMIntType(unsigned NumBits) { return LLVMIntTypeInContext(LLVMGetGlobalContext(), NumBits); } @@ -455,6 +461,11 @@ void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest) { *Dest++ = wrap(*I); } +LLVMTypeRef LLVMStructGetTypeAtIndex(LLVMTypeRef StructTy, unsigned i) { + StructType *Ty = unwrap<StructType>(StructTy); + return wrap(Ty->getTypeAtIndex(i)); +} + LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy) { return unwrap<StructType>(StructTy)->isPacked(); } @@ -1153,8 +1164,8 @@ LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices, unsigned NumIndices) { ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices), NumIndices); - return wrap(ConstantExpr::getGetElementPtr(unwrap<Constant>(ConstantVal), - IdxList)); + return wrap(ConstantExpr::getGetElementPtr( + nullptr, unwrap<Constant>(ConstantVal), IdxList)); } LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal, @@ -1163,7 +1174,7 @@ LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal, Constant* Val = unwrap<Constant>(ConstantVal); ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices), NumIndices); - return wrap(ConstantExpr::getInBoundsGetElementPtr(Val, IdxList)); + return wrap(ConstantExpr::getInBoundsGetElementPtr(nullptr, Val, IdxList)); } LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType) { @@ -1628,9 +1639,8 @@ void LLVMSetExternallyInitialized(LLVMValueRef GlobalVar, LLVMBool IsExtInit) { LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, const char *Name) { auto *PTy = cast<PointerType>(unwrap(Ty)); - return wrap(GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), - GlobalValue::ExternalLinkage, Name, - unwrap<GlobalObject>(Aliasee), unwrap(M))); + return wrap(GlobalAlias::create(PTy, GlobalValue::ExternalLinkage, Name, + unwrap<Constant>(Aliasee), unwrap(M))); } /*--.. Operations on functions .............................................--*/ @@ -2181,14 +2191,13 @@ void LLVMDisposeBuilder(LLVMBuilderRef Builder) { void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L) { MDNode *Loc = L ? cast<MDNode>(unwrap<MetadataAsValue>(L)->getMetadata()) : nullptr; - unwrap(Builder)->SetCurrentDebugLocation(DebugLoc::getFromDILocation(Loc)); + unwrap(Builder)->SetCurrentDebugLocation(DebugLoc(Loc)); } LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder) { LLVMContext &Context = unwrap(Builder)->getContext(); return wrap(MetadataAsValue::get( - Context, - unwrap(Builder)->getCurrentDebugLocation().getAsMDNode(Context))); + Context, unwrap(Builder)->getCurrentDebugLocation().getAsMDNode())); } void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst) { @@ -2240,11 +2249,8 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, } LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, - LLVMValueRef PersFn, unsigned NumClauses, - const char *Name) { - return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty), - cast<Function>(unwrap(PersFn)), - NumClauses, Name)); + unsigned NumClauses, const char *Name) { + return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty), NumClauses, Name)); } LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) { @@ -2506,19 +2512,20 @@ LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer, LLVMValueRef *Indices, unsigned NumIndices, const char *Name) { ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices); - return wrap(unwrap(B)->CreateGEP(unwrap(Pointer), IdxList, Name)); + return wrap(unwrap(B)->CreateGEP(nullptr, unwrap(Pointer), IdxList, Name)); } LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer, LLVMValueRef *Indices, unsigned NumIndices, const char *Name) { ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices); - return wrap(unwrap(B)->CreateInBoundsGEP(unwrap(Pointer), IdxList, Name)); + return wrap( + unwrap(B)->CreateInBoundsGEP(nullptr, unwrap(Pointer), IdxList, Name)); } LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer, unsigned Idx, const char *Name) { - return wrap(unwrap(B)->CreateStructGEP(unwrap(Pointer), Idx, Name)); + return wrap(unwrap(B)->CreateStructGEP(nullptr, unwrap(Pointer), Idx, Name)); } LLVMValueRef LLVMBuildGlobalString(LLVMBuilderRef B, const char *Str, @@ -2845,11 +2852,11 @@ LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void) { /*===-- Pass Manager ------------------------------------------------------===*/ LLVMPassManagerRef LLVMCreatePassManager() { - return wrap(new PassManager()); + return wrap(new legacy::PassManager()); } LLVMPassManagerRef LLVMCreateFunctionPassManagerForModule(LLVMModuleRef M) { - return wrap(new FunctionPassManager(unwrap(M))); + return wrap(new legacy::FunctionPassManager(unwrap(M))); } LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef P) { @@ -2858,19 +2865,19 @@ LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef P) { } LLVMBool LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { - return unwrap<PassManager>(PM)->run(*unwrap(M)); + return unwrap<legacy::PassManager>(PM)->run(*unwrap(M)); } LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM) { - return unwrap<FunctionPassManager>(FPM)->doInitialization(); + return unwrap<legacy::FunctionPassManager>(FPM)->doInitialization(); } LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F) { - return unwrap<FunctionPassManager>(FPM)->run(*unwrap<Function>(F)); + return unwrap<legacy::FunctionPassManager>(FPM)->run(*unwrap<Function>(F)); } LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM) { - return unwrap<FunctionPassManager>(FPM)->doFinalization(); + return unwrap<legacy::FunctionPassManager>(FPM)->doFinalization(); } void LLVMDisposePassManager(LLVMPassManagerRef PM) { diff --git a/contrib/llvm/lib/IR/DIBuilder.cpp b/contrib/llvm/lib/IR/DIBuilder.cpp index 856bb3c..c41d844 100644 --- a/contrib/llvm/lib/IR/DIBuilder.cpp +++ b/contrib/llvm/lib/IR/DIBuilder.cpp @@ -25,15 +25,24 @@ using namespace llvm::dwarf; namespace { class HeaderBuilder { + /// \brief Whether there are any fields yet. + /// + /// Note that this is not equivalent to \c Chars.empty(), since \a concat() + /// may have been called already with an empty string. + bool IsEmpty; 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)) {} + HeaderBuilder() : IsEmpty(true) {} + HeaderBuilder(const HeaderBuilder &X) : IsEmpty(X.IsEmpty), Chars(X.Chars) {} + HeaderBuilder(HeaderBuilder &&X) + : IsEmpty(X.IsEmpty), Chars(std::move(X.Chars)) {} template <class Twineable> HeaderBuilder &concat(Twineable &&X) { - Chars.push_back(0); + if (IsEmpty) + IsEmpty = false; + else + Chars.push_back(0); Twine(X).toVector(Chars); return *this; } @@ -43,10 +52,10 @@ public: } static HeaderBuilder get(unsigned Tag) { - return HeaderBuilder("0x" + Twine::utohexstr(Tag)); + return HeaderBuilder().concat("0x" + Twine::utohexstr(Tag)); } }; -} +} // namespace DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes) : M(m), VMContext(M.getContext()), TempEnumTypes(nullptr), @@ -54,24 +63,18 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes) DeclareFn(nullptr), ValueFn(nullptr), AllowUnresolvedNodes(AllowUnresolvedNodes) {} -static bool isUnresolved(MDNode *N) { - return N && - (isa<MDNodeFwdDecl>(N) || !cast<UniquableMDNode>(N)->isResolved()); -} - void DIBuilder::trackIfUnresolved(MDNode *N) { - if (!AllowUnresolvedNodes) { - assert(!isUnresolved(N) && "Cannot handle unresolved nodes"); + if (!N) return; - } - if (isUnresolved(N)) - UnresolvedNodes.emplace_back(N); - return; + if (N->isResolved()) + return; + + assert(AllowUnresolvedNodes && "Cannot handle unresolved nodes"); + UnresolvedNodes.emplace_back(N); } void DIBuilder::finalize() { - DIArray Enums = getOrCreateArray(AllEnumTypes); - DIType(TempEnumTypes).replaceAllUsesWith(Enums); + TempEnumTypes->replaceAllUsesWith(MDTuple::get(VMContext, AllEnumTypes)); SmallVector<Metadata *, 16> RetainValues; // Declarations and definitions of the same type may be retained. Some @@ -82,36 +85,30 @@ void DIBuilder::finalize() { for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++) if (RetainSet.insert(AllRetainTypes[I]).second) RetainValues.push_back(AllRetainTypes[I]); - DIArray RetainTypes = getOrCreateArray(RetainValues); - DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes); - - DIArray SPs = getOrCreateArray(AllSubprograms); - DIType(TempSubprograms).replaceAllUsesWith(SPs); - for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { - DISubprogram SP(SPs.getElement(i)); - if (MDNode *Temp = SP.getVariablesNodes()) { - SmallVector<Metadata *, 4> Variables; - for (Metadata *V : PreservedVariables.lookup(SP)) - Variables.push_back(V); - DIArray AV = getOrCreateArray(Variables); - DIType(Temp).replaceAllUsesWith(AV); + TempRetainTypes->replaceAllUsesWith(MDTuple::get(VMContext, RetainValues)); + + DISubprogramArray SPs = MDTuple::get(VMContext, AllSubprograms); + TempSubprograms->replaceAllUsesWith(SPs.get()); + for (auto *SP : SPs) { + if (MDTuple *Temp = SP->getVariables().get()) { + const auto &PV = PreservedVariables.lookup(SP); + SmallVector<Metadata *, 4> Variables(PV.begin(), PV.end()); + DINodeArray AV = getOrCreateArray(Variables); + TempMDTuple(Temp)->replaceAllUsesWith(AV.get()); } } - DIArray GVs = getOrCreateArray(AllGVs); - DIType(TempGVs).replaceAllUsesWith(GVs); + TempGVs->replaceAllUsesWith(MDTuple::get(VMContext, AllGVs)); - SmallVector<Metadata *, 16> RetainValuesI; - for (unsigned I = 0, E = AllImportedModules.size(); I < E; I++) - RetainValuesI.push_back(AllImportedModules[I]); - DIArray IMs = getOrCreateArray(RetainValuesI); - DIType(TempImportedModules).replaceAllUsesWith(IMs); + TempImportedModules->replaceAllUsesWith(MDTuple::get( + VMContext, SmallVector<Metadata *, 16>(AllImportedModules.begin(), + AllImportedModules.end()))); // Now that all temp nodes have been replaced or deleted, resolve remaining // cycles. for (const auto &N : UnresolvedNodes) - if (N) - cast<UniquableMDNode>(N)->resolveCycles(); + if (N && !N->isResolved()) + N->resolveCycles(); UnresolvedNodes.clear(); // Can't handle unresolved nodes anymore. @@ -119,58 +116,38 @@ void DIBuilder::finalize() { } /// If N is compile unit return NULL otherwise return N. -static MDNode *getNonCompileUnitScope(MDNode *N) { - if (DIDescriptor(N).isCompileUnit()) +static DIScope *getNonCompileUnitScope(DIScope *N) { + if (!N || isa<DICompileUnit>(N)) return nullptr; - return N; -} - -static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename, - StringRef Directory) { - assert(!Filename.empty() && "Unable to create file without name"); - Metadata *Pair[] = {MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory)}; - return MDNode::get(VMContext, Pair); + return cast<DIScope>(N); } -DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, - StringRef Directory, - StringRef Producer, bool isOptimized, - StringRef Flags, unsigned RunTimeVer, - StringRef SplitName, - DebugEmissionKind Kind, - bool EmitDebugInfo) { +DICompileUnit *DIBuilder::createCompileUnit( + unsigned Lang, StringRef Filename, StringRef Directory, StringRef Producer, + bool isOptimized, StringRef Flags, unsigned RunTimeVer, StringRef SplitName, + DebugEmissionKind Kind, uint64_t DWOId, bool EmitDebugInfo) { - assert(((Lang <= dwarf::DW_LANG_OCaml && Lang >= dwarf::DW_LANG_C89) || + assert(((Lang <= dwarf::DW_LANG_Fortran08 && Lang >= dwarf::DW_LANG_C89) || (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && "Invalid Language tag"); assert(!Filename.empty() && "Unable to create compile unit without filename"); - Metadata *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)}; - TempEnumTypes = MDNode::getTemporary(VMContext, TElts); - - TempRetainTypes = MDNode::getTemporary(VMContext, TElts); - - TempSubprograms = MDNode::getTemporary(VMContext, TElts); - TempGVs = MDNode::getTemporary(VMContext, TElts); - - TempImportedModules = MDNode::getTemporary(VMContext, TElts); - - Metadata *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); + // TODO: Once we make DICompileUnit distinct, stop using temporaries here + // (just start with operands assigned to nullptr). + TempEnumTypes = MDTuple::getTemporary(VMContext, None); + TempRetainTypes = MDTuple::getTemporary(VMContext, None); + TempSubprograms = MDTuple::getTemporary(VMContext, None); + TempGVs = MDTuple::getTemporary(VMContext, None); + TempImportedModules = MDTuple::getTemporary(VMContext, None); + + // TODO: Switch to getDistinct(). We never want to merge compile units based + // on contents. + DICompileUnit *CUNode = DICompileUnit::get( + VMContext, Lang, DIFile::get(VMContext, Filename, Directory), Producer, + isOptimized, Flags, RunTimeVer, SplitName, Kind, TempEnumTypes.get(), + TempRetainTypes.get(), TempSubprograms.get(), TempGVs.get(), + TempImportedModules.get(), DWOId); // Create a named metadata so that it is easier to find cu in a module. // Note that we only generate this when the caller wants to actually @@ -183,785 +160,475 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, } trackIfUnresolved(CUNode); - return DICompileUnit(CUNode); + return CUNode; } -static DIImportedEntity -createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope Context, +static DIImportedEntity * +createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context, Metadata *NS, unsigned Line, StringRef Name, SmallVectorImpl<TrackingMDNodeRef> &AllImportedModules) { - const MDNode *R; - Metadata *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.emplace_back(M.get()); + auto *M = DIImportedEntity::get(C, Tag, Context, DINodeRef(NS), Line, Name); + AllImportedModules.emplace_back(M); return M; } -DIImportedEntity DIBuilder::createImportedModule(DIScope Context, - DINameSpace NS, - unsigned Line) { +DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, + DINamespace *NS, + unsigned Line) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, Context, NS, Line, StringRef(), AllImportedModules); } -DIImportedEntity DIBuilder::createImportedModule(DIScope Context, - DIImportedEntity NS, - unsigned Line) { +DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, + DIImportedEntity *NS, + unsigned Line) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, Context, NS, Line, StringRef(), AllImportedModules); } -DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context, - DIDescriptor Decl, - unsigned Line, StringRef Name) { +DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context, + DINode *Decl, + unsigned Line, + StringRef Name) { // Make sure to use the unique identifier based metadata reference for // types that have one. - Metadata *V = - Decl.isType() ? static_cast<Metadata *>(DIType(Decl).getRef()) : Decl; return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration, - Context, V, Line, Name, + Context, DINodeRef::get(Decl), Line, Name, AllImportedModules); } -DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context, - DIImportedEntity Imp, - unsigned Line, StringRef Name) { - return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration, - Context, Imp, Line, Name, AllImportedModules); -} - -DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { - Metadata *Elts[] = { - HeaderBuilder::get(dwarf::DW_TAG_file_type).get(VMContext), - createFilePathPair(VMContext, Filename, Directory)}; - return DIFile(MDNode::get(VMContext, Elts)); +DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory) { + return DIFile::get(VMContext, Filename, Directory); } -DIEnumerator DIBuilder::createEnumerator(StringRef Name, int64_t Val) { +DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val) { assert(!Name.empty() && "Unable to create enumerator without name"); - Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_enumerator) - .concat(Name) - .concat(Val) - .get(VMContext)}; - return DIEnumerator(MDNode::get(VMContext, Elts)); + return DIEnumerator::get(VMContext, Val, Name); } -DIBasicType DIBuilder::createUnspecifiedType(StringRef Name) { +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. - Metadata *Elts[] = { - 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)); -} - -DIBasicType DIBuilder::createNullPtrType() { + return DIBasicType::get(VMContext, dwarf::DW_TAG_unspecified_type, Name); +} + +DIBasicType *DIBuilder::createNullPtrType() { return createUnspecifiedType("decltype(nullptr)"); } -DIBasicType -DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding) { +DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { assert(!Name.empty() && "Unable to create type without name"); - // Basic types are encoded in DIBasicType format. Line number, filename, - // offset and flags are always empty here. - Metadata *Elts[] = { - 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)); -} - -DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { - // Qualified types are encoded in DIDerivedType format. - Metadata *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)); -} - -DIDerivedType -DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, - uint64_t AlignInBits, StringRef Name) { - // Pointer types are encoded in DIDerivedType format. - Metadata *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, - uint64_t SizeInBits, uint64_t AlignInBits) { - // Pointer types are encoded in DIDerivedType format. - Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_ptr_to_member_type) - .concat(StringRef()) - .concat(0) // Line - .concat(SizeInBits) // Size - .concat(AlignInBits) // Align - .concat(0) // Offset - .concat(0) // Flags - .get(VMContext), - nullptr, // Filename - nullptr, // Unused - PointeeTy.getRef(), Base.getRef()}; - return DIDerivedType(MDNode::get(VMContext, Elts)); -} - -DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { - assert(RTy.isType() && "Unable to create reference type"); - // References are encoded in DIDerivedType format. - Metadata *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)); -} - -DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, - unsigned LineNo, DIDescriptor Context) { - // typedefs are encoded in DIDerivedType format. - Metadata *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)); -} - -DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { - // typedefs are encoded in DIDerivedType format. - assert(Ty.isType() && "Invalid type!"); - assert(FriendTy.isType() && "Invalid friend type!"); - Metadata *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)); -} - -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. - Metadata *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)); -} - -DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType Ty) { - // TAG_member is encoded in DIDerivedType format. - Metadata *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)); -} - -static Metadata *getConstantOrNull(Constant *C) { + return DIBasicType::get(VMContext, dwarf::DW_TAG_base_type, Name, SizeInBits, + AlignInBits, Encoding); +} + +DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { + return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, + DITypeRef::get(FromTy), 0, 0, 0, 0); +} + +DIDerivedType *DIBuilder::createPointerType(DIType *PointeeTy, + uint64_t SizeInBits, + uint64_t AlignInBits, + StringRef Name) { + // FIXME: Why is there a name here? + return DIDerivedType::get(VMContext, dwarf::DW_TAG_pointer_type, Name, + nullptr, 0, nullptr, DITypeRef::get(PointeeTy), + SizeInBits, AlignInBits, 0, 0); +} + +DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, + DIType *Base, + uint64_t SizeInBits, + uint64_t AlignInBits) { + return DIDerivedType::get(VMContext, dwarf::DW_TAG_ptr_to_member_type, "", + nullptr, 0, nullptr, DITypeRef::get(PointeeTy), + SizeInBits, AlignInBits, 0, 0, + DITypeRef::get(Base)); +} + +DIDerivedType *DIBuilder::createReferenceType(unsigned Tag, DIType *RTy) { + assert(RTy && "Unable to create reference type"); + return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, + DITypeRef::get(RTy), 0, 0, 0, 0); +} + +DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, + DIFile *File, unsigned LineNo, + DIScope *Context) { + return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, + LineNo, + DIScopeRef::get(getNonCompileUnitScope(Context)), + DITypeRef::get(Ty), 0, 0, 0, 0); +} + +DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { + assert(Ty && "Invalid type!"); + assert(FriendTy && "Invalid friend type!"); + return DIDerivedType::get(VMContext, dwarf::DW_TAG_friend, "", nullptr, 0, + DITypeRef::get(Ty), DITypeRef::get(FriendTy), 0, 0, + 0, 0); +} + +DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy, + uint64_t BaseOffset, + unsigned Flags) { + assert(Ty && "Unable to create inheritance"); + return DIDerivedType::get(VMContext, dwarf::DW_TAG_inheritance, "", nullptr, + 0, DITypeRef::get(Ty), DITypeRef::get(BaseTy), 0, 0, + BaseOffset, Flags); +} + +DIDerivedType *DIBuilder::createMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, + unsigned Flags, DIType *Ty) { + return DIDerivedType::get( + VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(Scope)), DITypeRef::get(Ty), + SizeInBits, AlignInBits, OffsetInBits, Flags); +} + +static ConstantAsMetadata *getConstantOrNull(Constant *C) { if (C) return ConstantAsMetadata::get(C); return nullptr; } -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; - Metadata *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(), getConstantOrNull(Val)}; - return DIDerivedType(MDNode::get(VMContext, Elts)); -} - -DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType Ty, MDNode *PropertyNode) { - // TAG_member is encoded in DIDerivedType format. - Metadata *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)); -} - -DIObjCProperty -DIBuilder::createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber, +DIDerivedType *DIBuilder::createStaticMemberType(DIScope *Scope, StringRef Name, + DIFile *File, + unsigned LineNumber, + DIType *Ty, unsigned Flags, + llvm::Constant *Val) { + Flags |= DINode::FlagStaticMember; + return DIDerivedType::get( + VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(Scope)), DITypeRef::get(Ty), 0, 0, + 0, Flags, getConstantOrNull(Val)); +} + +DIDerivedType *DIBuilder::createObjCIVar(StringRef Name, DIFile *File, + unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *Ty, MDNode *PropertyNode) { + return DIDerivedType::get( + VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(File)), DITypeRef::get(Ty), + SizeInBits, AlignInBits, OffsetInBits, Flags, PropertyNode); +} + +DIObjCProperty * +DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber, StringRef GetterName, StringRef SetterName, - unsigned PropertyAttributes, DIType Ty) { - Metadata *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)); -} - -DITemplateTypeParameter -DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, - DIType Ty, MDNode *File, unsigned LineNo, - unsigned ColumnNo) { - Metadata *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)); -} - -static DITemplateValueParameter createTemplateValueParameterHelper( - LLVMContext &VMContext, unsigned Tag, DIDescriptor Context, StringRef Name, - DIType Ty, Metadata *MD, MDNode *File, unsigned LineNo, unsigned ColumnNo) { - Metadata *Elts[] = { - HeaderBuilder::get(Tag).concat(Name).concat(LineNo).concat(ColumnNo).get( - VMContext), - DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), MD, File}; - return DITemplateValueParameter(MDNode::get(VMContext, Elts)); -} - -DITemplateValueParameter -DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, - DIType Ty, Constant *Val, MDNode *File, - unsigned LineNo, unsigned ColumnNo) { + unsigned PropertyAttributes, DIType *Ty) { + return DIObjCProperty::get(VMContext, Name, File, LineNumber, GetterName, + SetterName, PropertyAttributes, + DITypeRef::get(Ty)); +} + +DITemplateTypeParameter * +DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name, + DIType *Ty) { + assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit"); + return DITemplateTypeParameter::get(VMContext, Name, DITypeRef::get(Ty)); +} + +static DITemplateValueParameter * +createTemplateValueParameterHelper(LLVMContext &VMContext, unsigned Tag, + DIScope *Context, StringRef Name, DIType *Ty, + Metadata *MD) { + assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit"); + return DITemplateValueParameter::get(VMContext, Tag, Name, DITypeRef::get(Ty), + MD); +} + +DITemplateValueParameter * +DIBuilder::createTemplateValueParameter(DIScope *Context, StringRef Name, + DIType *Ty, Constant *Val) { return createTemplateValueParameterHelper( VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty, - getConstantOrNull(Val), File, LineNo, ColumnNo); + getConstantOrNull(Val)); } -DITemplateValueParameter -DIBuilder::createTemplateTemplateParameter(DIDescriptor Context, StringRef Name, - DIType Ty, StringRef Val, - MDNode *File, unsigned LineNo, - unsigned ColumnNo) { +DITemplateValueParameter * +DIBuilder::createTemplateTemplateParameter(DIScope *Context, StringRef Name, + DIType *Ty, StringRef Val) { return createTemplateValueParameterHelper( VMContext, dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty, - MDString::get(VMContext, Val), File, LineNo, ColumnNo); + MDString::get(VMContext, Val)); } -DITemplateValueParameter -DIBuilder::createTemplateParameterPack(DIDescriptor Context, StringRef Name, - DIType Ty, DIArray Val, - MDNode *File, unsigned LineNo, - unsigned ColumnNo) { +DITemplateValueParameter * +DIBuilder::createTemplateParameterPack(DIScope *Context, StringRef Name, + DIType *Ty, DINodeArray Val) { return createTemplateValueParameterHelper( VMContext, dwarf::DW_TAG_GNU_template_parameter_pack, Context, Name, Ty, - Val, File, LineNo, ColumnNo); + Val.get()); } -DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, - DIType VTableHolder, - MDNode *TemplateParams, - StringRef UniqueIdentifier) { - assert((!Context || Context.isScope() || Context.isType()) && +DICompositeType *DIBuilder::createClassType( + DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType *DerivedFrom, DINodeArray Elements, + DIType *VTableHolder, MDNode *TemplateParams, StringRef UniqueIdentifier) { + assert((!Context || isa<DIScope>(Context)) && "createClassType should be called with a valid Context"); - // TAG_class_type is encoded in DICompositeType format. - Metadata *Elts[] = { - 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"); + + auto *R = DICompositeType::get( + VMContext, dwarf::DW_TAG_structure_type, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(Context)), + DITypeRef::get(DerivedFrom), SizeInBits, AlignInBits, OffsetInBits, Flags, + Elements, 0, DITypeRef::get(VTableHolder), + cast_or_null<MDTuple>(TemplateParams), UniqueIdentifier); if (!UniqueIdentifier.empty()) retainType(R); + trackIfUnresolved(R); return R; } -DICompositeType DIBuilder::createStructType(DIDescriptor Context, - StringRef Name, DIFile File, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, - unsigned RunTimeLang, - DIType VTableHolder, - StringRef UniqueIdentifier) { - // TAG_structure_type is encoded in DICompositeType format. - Metadata *Elts[] = { - 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"); +DICompositeType *DIBuilder::createStructType( + DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang, + DIType *VTableHolder, StringRef UniqueIdentifier) { + auto *R = DICompositeType::get( + VMContext, dwarf::DW_TAG_structure_type, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(Context)), + DITypeRef::get(DerivedFrom), SizeInBits, AlignInBits, 0, Flags, Elements, + RunTimeLang, DITypeRef::get(VTableHolder), nullptr, UniqueIdentifier); if (!UniqueIdentifier.empty()) retainType(R); + trackIfUnresolved(R); return R; } -DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Flags, - DIArray Elements, - unsigned RunTimeLang, - StringRef UniqueIdentifier) { - // TAG_union_type is encoded in DICompositeType format. - Metadata *Elts[] = { - 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)); +DICompositeType *DIBuilder::createUnionType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + DINodeArray Elements, unsigned RunTimeLang, StringRef UniqueIdentifier) { + auto *R = DICompositeType::get( + VMContext, dwarf::DW_TAG_union_type, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(Scope)), nullptr, SizeInBits, + AlignInBits, 0, Flags, Elements, RunTimeLang, nullptr, nullptr, + UniqueIdentifier); if (!UniqueIdentifier.empty()) retainType(R); + trackIfUnresolved(R); return R; } -DISubroutineType DIBuilder::createSubroutineType(DIFile File, - DITypeArray ParameterTypes, - unsigned Flags) { - // TAG_subroutine_type is encoded in DICompositeType format. - Metadata *Elts[] = { - 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 DISubroutineType(MDNode::get(VMContext, Elts)); -} - -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. - Metadata *Elts[] = { - 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)); +DISubroutineType *DIBuilder::createSubroutineType(DIFile *File, + DITypeRefArray ParameterTypes, + unsigned Flags) { + return DISubroutineType::get(VMContext, Flags, ParameterTypes); +} + +DICompositeType *DIBuilder::createEnumerationType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements, + DIType *UnderlyingType, StringRef UniqueIdentifier) { + auto *CTy = DICompositeType::get( + VMContext, dwarf::DW_TAG_enumeration_type, Name, File, LineNumber, + DIScopeRef::get(getNonCompileUnitScope(Scope)), + DITypeRef::get(UnderlyingType), SizeInBits, AlignInBits, 0, 0, Elements, + 0, nullptr, nullptr, UniqueIdentifier); AllEnumTypes.push_back(CTy); if (!UniqueIdentifier.empty()) retainType(CTy); + trackIfUnresolved(CTy); return CTy; } -DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts) { - // TAG_array_type is encoded in DICompositeType format. - Metadata *Elts[] = { - 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)); -} - -DICompositeType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts) { - // A vector is an array type with the FlagVector flag applied. - Metadata *Elts[] = { - 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)); -} - -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<Metadata *, 9> Elts; - MDNode *N = Ty; - 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)); - - return DIType(MDNode::get(Context, Elts)); -} - -DIType DIBuilder::createArtificialType(DIType Ty) { - if (Ty.isArtificial()) +DICompositeType *DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, + DINodeArray Subscripts) { + auto *R = DICompositeType::get(VMContext, dwarf::DW_TAG_array_type, "", + nullptr, 0, nullptr, DITypeRef::get(Ty), Size, + AlignInBits, 0, 0, Subscripts, 0, nullptr); + trackIfUnresolved(R); + return R; +} + +DICompositeType *DIBuilder::createVectorType(uint64_t Size, + uint64_t AlignInBits, DIType *Ty, + DINodeArray Subscripts) { + auto *R = + DICompositeType::get(VMContext, dwarf::DW_TAG_array_type, "", nullptr, 0, + nullptr, DITypeRef::get(Ty), Size, AlignInBits, 0, + DINode::FlagVector, Subscripts, 0, nullptr); + trackIfUnresolved(R); + return R; +} + +static DIType *createTypeWithFlags(LLVMContext &Context, DIType *Ty, + unsigned FlagsToSet) { + auto NewTy = Ty->clone(); + NewTy->setFlags(NewTy->getFlags() | FlagsToSet); + return MDNode::replaceWithUniqued(std::move(NewTy)); +} + +DIType *DIBuilder::createArtificialType(DIType *Ty) { + // FIXME: Restrict this to the nodes where it's valid. + if (Ty->isArtificial()) return Ty; - return createTypeWithFlags(VMContext, Ty, DIType::FlagArtificial); + return createTypeWithFlags(VMContext, Ty, DINode::FlagArtificial); } -DIType DIBuilder::createObjectPointerType(DIType Ty) { - if (Ty.isObjectPointer()) +DIType *DIBuilder::createObjectPointerType(DIType *Ty) { + // FIXME: Restrict this to the nodes where it's valid. + if (Ty->isObjectPointer()) return Ty; - unsigned Flags = DIType::FlagObjectPointer | DIType::FlagArtificial; + unsigned Flags = DINode::FlagObjectPointer | DINode::FlagArtificial; return createTypeWithFlags(VMContext, Ty, Flags); } -void DIBuilder::retainType(DIType T) { AllRetainTypes.emplace_back(T); } - -DIBasicType DIBuilder::createUnspecifiedParameter() { - return DIBasicType(); +void DIBuilder::retainType(DIType *T) { + assert(T && "Expected non-null type"); + AllRetainTypes.emplace_back(T); } -DICompositeType -DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, - DIFile F, unsigned Line, unsigned RuntimeLang, +DIBasicType *DIBuilder::createUnspecifiedParameter() { return nullptr; } + +DICompositeType * +DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, + DIFile *F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, StringRef UniqueIdentifier) { - // Create a temporary MDNode. - Metadata *Elts[] = { - 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() && - "createForwardDecl result should be a DIType"); + // FIXME: Define in terms of createReplaceableForwardDecl() by calling + // replaceWithUniqued(). + auto *RetTy = DICompositeType::get( + VMContext, Tag, Name, F, Line, + DIScopeRef::get(getNonCompileUnitScope(Scope)), nullptr, SizeInBits, + AlignInBits, 0, DINode::FlagFwdDecl, nullptr, RuntimeLang, nullptr, + nullptr, UniqueIdentifier); if (!UniqueIdentifier.empty()) retainType(RetTy); + trackIfUnresolved(RetTy); return RetTy; } -DICompositeType DIBuilder::createReplaceableForwardDecl( - unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, +DICompositeType *DIBuilder::createReplaceableCompositeType( + unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, - StringRef UniqueIdentifier) { - // Create a temporary MDNode. - Metadata *Elts[] = { - 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)}; - DICompositeType RetTy(MDNode::getTemporary(VMContext, Elts)); - assert(RetTy.isCompositeType() && - "createReplaceableForwardDecl result should be a DIType"); + unsigned Flags, StringRef UniqueIdentifier) { + auto *RetTy = DICompositeType::getTemporary( + VMContext, Tag, Name, F, Line, + DIScopeRef::get(getNonCompileUnitScope(Scope)), nullptr, + SizeInBits, AlignInBits, 0, Flags, nullptr, RuntimeLang, + nullptr, nullptr, UniqueIdentifier) + .release(); if (!UniqueIdentifier.empty()) retainType(RetTy); + trackIfUnresolved(RetTy); return RetTy; } -DIArray DIBuilder::getOrCreateArray(ArrayRef<Metadata *> Elements) { - return DIArray(MDNode::get(VMContext, Elements)); +DINodeArray DIBuilder::getOrCreateArray(ArrayRef<Metadata *> Elements) { + return MDTuple::get(VMContext, Elements); } -DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef<Metadata *> Elements) { +DITypeRefArray DIBuilder::getOrCreateTypeArray(ArrayRef<Metadata *> Elements) { SmallVector<llvm::Metadata *, 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()); + Elts.push_back(DITypeRef::get(cast<DIType>(Elements[i]))); else Elts.push_back(Elements[i]); } - return DITypeArray(MDNode::get(VMContext, Elts)); + return DITypeRefArray(MDNode::get(VMContext, Elts)); } -DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) { - Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subrange_type) - .concat(Lo) - .concat(Count) - .get(VMContext)}; - - return DISubrange(MDNode::get(VMContext, Elts)); +DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) { + return DISubrange::get(VMContext, Count, Lo); } -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<Metadata *>)> CreateFunc) { - - MDNode *TheCtx = getNonCompileUnitScope(Context); - if (DIScope(TheCtx).isCompositeType()) { - assert(!DICompositeType(TheCtx).getIdentifier() && +static void checkGlobalVariableScope(DIScope *Context) { +#ifndef NDEBUG + if (auto *CT = + dyn_cast_or_null<DICompositeType>(getNonCompileUnitScope(Context))) + assert(CT->getIdentifier().empty() && "Context of a global variable should not be a type with identifier"); - } +#endif +} - Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_variable) - .concat(Name) - .concat(Name) - .concat(LinkageName) - .concat(LineNumber) - .concat(isLocalToUnit) - .concat(isDefinition) - .get(VMContext), - TheCtx, F, Ty, getConstantOrNull(Val), - DIDescriptor(Decl)}; +DIGlobalVariable *DIBuilder::createGlobalVariable( + DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, + unsigned LineNumber, DIType *Ty, bool isLocalToUnit, Constant *Val, + MDNode *Decl) { + checkGlobalVariableScope(Context); - return DIGlobalVariable(CreateFunc(Elts)); + auto *N = DIGlobalVariable::get(VMContext, cast_or_null<DIScope>(Context), + Name, LinkageName, F, LineNumber, + DITypeRef::get(Ty), isLocalToUnit, true, Val, + cast_or_null<DIDerivedType>(Decl)); + AllGVs.push_back(N); + return N; } -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<Metadata *> 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, +DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( + DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, + unsigned LineNumber, DIType *Ty, bool isLocalToUnit, Constant *Val, MDNode *Decl) { - return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F, - LineNumber, Ty, isLocalToUnit, Val, Decl, - false, [&](ArrayRef<Metadata *> Elts) { - return MDNode::getTemporary(VMContext, Elts); - }); -} - -DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIFile File, - unsigned LineNo, DITypeRef Ty, - bool AlwaysPreserve, unsigned Flags, - unsigned ArgNo) { - DIDescriptor Context(getNonCompileUnitScope(Scope)); - assert((!Context || Context.isScope()) && - "createLocalVariable should be called with a valid Context"); - Metadata *Elts[] = {HeaderBuilder::get(Tag) - .concat(Name) - .concat(LineNo | (ArgNo << 24)) - .concat(Flags) - .get(VMContext), - getNonCompileUnitScope(Scope), File, Ty}; - MDNode *Node = MDNode::get(VMContext, Elts); + checkGlobalVariableScope(Context); + + return DIGlobalVariable::getTemporary( + VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F, + LineNumber, DITypeRef::get(Ty), isLocalToUnit, false, Val, + cast_or_null<DIDerivedType>(Decl)) + .release(); +} + +DILocalVariable *DIBuilder::createLocalVariable( + unsigned Tag, DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, + DIType *Ty, bool AlwaysPreserve, unsigned Flags, unsigned ArgNo) { + // FIXME: Why getNonCompileUnitScope()? + // FIXME: Why is "!Context" okay here? + // FIXME: WHy doesn't this check for a subprogram or lexical block (AFAICT + // the only valid scopes)? + DIScope *Context = getNonCompileUnitScope(Scope); + + auto *Node = DILocalVariable::get( + VMContext, Tag, cast_or_null<DILocalScope>(Context), Name, File, LineNo, + DITypeRef::get(Ty), ArgNo, Flags); 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)); + DISubprogram *Fn = getDISubprogram(Scope); assert(Fn && "Missing subprogram for local variable"); PreservedVariables[Fn].emplace_back(Node); } - DIVariable RetVar(Node); - assert(RetVar.isVariable() && - "createLocalVariable should return a valid DIVariable"); - return RetVar; + return Node; } -DIExpression DIBuilder::createExpression(ArrayRef<int64_t> Addr) { - auto Header = HeaderBuilder::get(DW_TAG_expression); - for (int64_t I : Addr) - Header.concat(I); - Metadata *Elts[] = {Header.get(VMContext)}; - return DIExpression(MDNode::get(VMContext, Elts)); +DIExpression *DIBuilder::createExpression(ArrayRef<uint64_t> Addr) { + return DIExpression::get(VMContext, Addr); } -DIExpression DIBuilder::createPieceExpression(unsigned OffsetInBytes, - unsigned SizeInBytes) { - int64_t Addr[] = {dwarf::DW_OP_piece, OffsetInBytes, SizeInBytes}; +DIExpression *DIBuilder::createExpression(ArrayRef<int64_t> Signed) { + // TODO: Remove the callers of this signed version and delete. + SmallVector<uint64_t, 8> Addr(Signed.begin(), Signed.end()); return createExpression(Addr); } -DISubprogram DIBuilder::createFunction(DIScopeRef 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) { +DIExpression *DIBuilder::createBitPieceExpression(unsigned OffsetInBytes, + unsigned SizeInBytes) { + uint64_t Addr[] = {dwarf::DW_OP_bit_piece, OffsetInBytes, SizeInBytes}; + return DIExpression::get(VMContext, Addr); +} + +DISubprogram *DIBuilder::createFunction(DIScopeRef Context, StringRef Name, + StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, + unsigned ScopeLine, unsigned Flags, + bool isOptimized, Function *Fn, + MDNode *TParams, MDNode *Decl) { // dragonegg does not generate identifier for types, so using an empty map // to resolve the context should be fine. DITypeIdentifierMap EmptyMap; @@ -970,161 +637,84 @@ DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name, Flags, isOptimized, Fn, TParams, Decl); } -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<Metadata *>)> CreateFunc) { - assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type && +DISubprogram *DIBuilder::createFunction(DIScope *Context, StringRef Name, + StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, + 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"); - Metadata *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, getConstantOrNull(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, - 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, - MDNode::getTemporary(VMContext, None), - [&](ArrayRef<Metadata *> 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; - }); -} - -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<Metadata *> Elts) { - return MDNode::getTemporary(VMContext, Elts); - }); -} - -DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile F, - unsigned LineNo, DICompositeType Ty, - bool isLocalToUnit, bool isDefinition, - unsigned VK, unsigned VIndex, - DIType VTableHolder, unsigned Flags, - bool isOptimized, Function *Fn, - MDNode *TParam) { - assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type && + auto *Node = DISubprogram::get( + VMContext, DIScopeRef::get(getNonCompileUnitScope(Context)), Name, + LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, + nullptr, 0, 0, Flags, isOptimized, Fn, cast_or_null<MDTuple>(TParams), + cast_or_null<DISubprogram>(Decl), + MDTuple::getTemporary(VMContext, None).release()); + + if (isDefinition) + AllSubprograms.push_back(Node); + trackIfUnresolved(Node); + return Node; +} + +DISubprogram *DIBuilder::createTempFunctionFwdDecl( + DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, + bool isDefinition, unsigned ScopeLine, unsigned Flags, bool isOptimized, + Function *Fn, MDNode *TParams, MDNode *Decl) { + return DISubprogram::getTemporary( + VMContext, DIScopeRef::get(getNonCompileUnitScope(Context)), Name, + LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, + ScopeLine, nullptr, 0, 0, Flags, isOptimized, Fn, + cast_or_null<MDTuple>(TParams), cast_or_null<DISubprogram>(Decl), + nullptr) + .release(); +} + +DISubprogram * +DIBuilder::createMethod(DIScope *Context, StringRef Name, StringRef LinkageName, + DIFile *F, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned VK, + unsigned VIndex, DIType *VTableHolder, unsigned Flags, + bool isOptimized, Function *Fn, MDNode *TParam) { + assert(Ty->getTag() == dwarf::DW_TAG_subroutine_type && "function types should be subroutines"); assert(getNonCompileUnitScope(Context) && "Methods should have both a Context and a context that isn't " "the compile unit."); - Metadata *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(), getConstantOrNull(Fn), TParam, - nullptr, nullptr}; - MDNode *Node = MDNode::get(VMContext, Elts); + // FIXME: Do we want to use different scope/lines? + auto *SP = DISubprogram::get( + VMContext, DIScopeRef::get(cast<DIScope>(Context)), Name, LinkageName, F, + LineNo, Ty, isLocalToUnit, isDefinition, LineNo, + DITypeRef::get(VTableHolder), VK, VIndex, Flags, isOptimized, Fn, + cast_or_null<MDTuple>(TParam), nullptr, nullptr); + if (isDefinition) - AllSubprograms.push_back(Node); - DISubprogram S(Node); - assert(S.isSubprogram() && "createMethod should return a valid DISubprogram"); - return S; -} - -DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo) { - Metadata *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; + AllSubprograms.push_back(SP); + trackIfUnresolved(SP); + return SP; } -DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, - DIFile File, - unsigned Discriminator) { - Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block) - .concat(Discriminator) - .get(VMContext), - File.getFileNode(), Scope}; - DILexicalBlockFile R(MDNode::get(VMContext, Elts)); - assert( - R.Verify() && - "createLexicalBlockFile should return a verifiable DILexicalBlockFile"); - return R; +DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo) { + return DINamespace::get(VMContext, getNonCompileUnitScope(Scope), File, Name, + LineNo); } -DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, - 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 - // documentation (SourceLevelDebugging.rst) claims the line/col are necessary - // for uniquing, yet then we have this other solution (because line/col were - // inadequate) anyway. Remove all 3 and replace them with a self-reference. - - // Defeat MDNode uniquing for lexical blocks by using unique id. - static unsigned int unique_id = 0; - Metadata *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; +DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope, + DIFile *File, + unsigned Discriminator) { + return DILexicalBlockFile::get(VMContext, Scope, File, Discriminator); +} + +DILexicalBlock *DIBuilder::createLexicalBlock(DIScope *Scope, DIFile *File, + unsigned Line, unsigned Col) { + // Make these distinct, to avoid merging two lexical blocks on the same + // file/line/column. + return DILexicalBlock::getDistinct(VMContext, getNonCompileUnitScope(Scope), + File, Line, Col); } static Value *getDbgIntrinsicValueImpl(LLVMContext &VMContext, Value *V) { @@ -1132,11 +722,19 @@ static Value *getDbgIntrinsicValueImpl(LLVMContext &VMContext, Value *V) { return MetadataAsValue::get(VMContext, ValueAsMetadata::get(V)); } -Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, - DIExpression Expr, +static Instruction *withDebugLoc(Instruction *I, const DILocation *DL) { + I->setDebugLoc(const_cast<DILocation *>(DL)); + return I; +} + +Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, Instruction *InsertBefore) { - assert(VarInfo.isVariable() && - "empty or invalid DIVariable passed to dbg.declare"); + assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); @@ -1145,14 +743,17 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage), MetadataAsValue::get(VMContext, VarInfo), MetadataAsValue::get(VMContext, Expr)}; - return CallInst::Create(DeclareFn, Args, "", InsertBefore); + return withDebugLoc(CallInst::Create(DeclareFn, Args, "", InsertBefore), DL); } -Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, - DIExpression Expr, +Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, BasicBlock *InsertAtEnd) { - assert(VarInfo.isVariable() && - "empty or invalid DIVariable passed to dbg.declare"); + assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); @@ -1165,18 +766,21 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, // If this block already has a terminator then insert this intrinsic // before the terminator. if (TerminatorInst *T = InsertAtEnd->getTerminator()) - return CallInst::Create(DeclareFn, Args, "", T); - else - return CallInst::Create(DeclareFn, Args, "", InsertAtEnd); + return withDebugLoc(CallInst::Create(DeclareFn, Args, "", T), DL); + return withDebugLoc(CallInst::Create(DeclareFn, Args, "", InsertAtEnd), DL); } Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable VarInfo, - DIExpression Expr, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, Instruction *InsertBefore) { assert(V && "no value passed to dbg.value"); - assert(VarInfo.isVariable() && - "empty or invalid DIVariable passed to dbg.value"); + assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.value"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); @@ -1186,16 +790,20 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, ConstantInt::get(Type::getInt64Ty(VMContext), Offset), MetadataAsValue::get(VMContext, VarInfo), MetadataAsValue::get(VMContext, Expr)}; - return CallInst::Create(ValueFn, Args, "", InsertBefore); + return withDebugLoc(CallInst::Create(ValueFn, Args, "", InsertBefore), DL); } Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable VarInfo, - DIExpression Expr, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertAtEnd) { assert(V && "no value passed to dbg.value"); - assert(VarInfo.isVariable() && - "empty or invalid DIVariable passed to dbg.value"); + assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.value"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); @@ -1205,27 +813,40 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, ConstantInt::get(Type::getInt64Ty(VMContext), Offset), MetadataAsValue::get(VMContext, VarInfo), MetadataAsValue::get(VMContext, Expr)}; - return CallInst::Create(ValueFn, Args, "", InsertAtEnd); + + return withDebugLoc(CallInst::Create(ValueFn, Args, "", InsertAtEnd), DL); } -void DIBuilder::replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder) { - T.setContainingType(VTableHolder); +void DIBuilder::replaceVTableHolder(DICompositeType *&T, + DICompositeType *VTableHolder) { + { + TypedTrackingMDRef<DICompositeType> N(T); + N->replaceVTableHolder(DITypeRef::get(VTableHolder)); + T = N.get(); + } // If this didn't create a self-reference, just return. if (T != VTableHolder) return; - // Look for unresolved operands. T has dropped RAUW support and is already - // marked resolved, orphaning any cycles underneath it. - assert(T->isResolved() && "Expected self-reference to be resolved"); - for (const MDOperand &O : T->operands()) - if (auto *N = dyn_cast_or_null<MDNode>(O)) - trackIfUnresolved(N); -} - -void DIBuilder::replaceArrays(DICompositeType &T, DIArray Elements, - DIArray TParams) { - T.setArrays(Elements, TParams); + // Look for unresolved operands. T will drop RAUW support, orphaning any + // cycles underneath it. + if (T->isResolved()) + for (const MDOperand &O : T->operands()) + if (auto *N = dyn_cast_or_null<MDNode>(O)) + trackIfUnresolved(N); +} + +void DIBuilder::replaceArrays(DICompositeType *&T, DINodeArray Elements, + DINodeArray TParams) { + { + TypedTrackingMDRef<DICompositeType> N(T); + if (Elements) + N->replaceElements(Elements); + if (TParams) + N->replaceTemplateParams(DITemplateParameterArray(TParams)); + T = N.get(); + } // If T isn't resolved, there's no problem. if (!T->isResolved()) @@ -1235,7 +856,7 @@ void DIBuilder::replaceArrays(DICompositeType &T, DIArray Elements, // arrays explicitly if they're unresolved, or else the cycles will be // orphaned. if (Elements) - trackIfUnresolved(Elements); + trackIfUnresolved(Elements.get()); if (TParams) - trackIfUnresolved(TParams); + trackIfUnresolved(TParams.get()); } diff --git a/contrib/llvm/lib/IR/DataLayout.cpp b/contrib/llvm/lib/IR/DataLayout.cpp index cde3937..4d867ef 100644 --- a/contrib/llvm/lib/IR/DataLayout.cpp +++ b/contrib/llvm/lib/IR/DataLayout.cpp @@ -33,11 +33,6 @@ #include <cstdlib> using namespace llvm; -// Handle the Pass registration stuff necessary to use DataLayout's. - -INITIALIZE_PASS(DataLayoutPass, "datalayout", "Data Layout", false, true) -char DataLayoutPass::ID = 0; - //===----------------------------------------------------------------------===// // Support for StructLayout //===----------------------------------------------------------------------===// @@ -155,8 +150,8 @@ DataLayout::InvalidPointerElem = { 0U, 0U, 0U, ~0U }; const char *DataLayout::getManglingComponent(const Triple &T) { if (T.isOSBinFormatMachO()) return "-m:o"; - if (T.isOSWindows() && T.getArch() == Triple::x86 && T.isOSBinFormatCOFF()) - return "-m:w"; + if (T.isOSWindows() && T.isOSBinFormatCOFF()) + return T.getArch() == Triple::x86 ? "-m:x" : "-m:w"; return "-m:e"; } @@ -221,6 +216,7 @@ static unsigned inBytes(unsigned Bits) { } void DataLayout::parseSpecifier(StringRef Desc) { + StringRepresentation = Desc; while (!Desc.empty()) { // Split at '-'. std::pair<StringRef, StringRef> Split = split(Desc, '-'); @@ -259,6 +255,8 @@ void DataLayout::parseSpecifier(StringRef Desc) { "Missing size specification for pointer in datalayout string"); Split = split(Rest, ':'); unsigned PointerMemSize = inBytes(getInt(Tok)); + if (!PointerMemSize) + report_fatal_error("Invalid pointer size of 0 bytes"); // ABI alignment. if (Rest.empty()) @@ -266,12 +264,18 @@ void DataLayout::parseSpecifier(StringRef Desc) { "Missing alignment specification for pointer in datalayout string"); Split = split(Rest, ':'); unsigned PointerABIAlign = inBytes(getInt(Tok)); + if (!isPowerOf2_64(PointerABIAlign)) + report_fatal_error( + "Pointer ABI alignment must be a power of 2"); // Preferred alignment. unsigned PointerPrefAlign = PointerABIAlign; if (!Rest.empty()) { Split = split(Rest, ':'); PointerPrefAlign = inBytes(getInt(Tok)); + if (!isPowerOf2_64(PointerPrefAlign)) + report_fatal_error( + "Pointer preferred alignment must be a power of 2"); } setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign, @@ -304,6 +308,9 @@ void DataLayout::parseSpecifier(StringRef Desc) { "Missing alignment specification in datalayout string"); Split = split(Rest, ':'); unsigned ABIAlign = inBytes(getInt(Tok)); + if (AlignType != AGGREGATE_ALIGN && !ABIAlign) + report_fatal_error( + "ABI alignment specification must be >0 for non-aggregate types"); // Preferred alignment. unsigned PrefAlign = ABIAlign; @@ -352,7 +359,10 @@ void DataLayout::parseSpecifier(StringRef Desc) { ManglingMode = MM_Mips; break; case 'w': - ManglingMode = MM_WINCOFF; + ManglingMode = MM_WinCOFF; + break; + case 'x': + ManglingMode = MM_WinCOFFX86; break; } break; @@ -367,13 +377,7 @@ DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) { init(M); } -void DataLayout::init(const Module *M) { - const DataLayout *Other = M->getDataLayout(); - if (Other) - *this = *Other; - else - reset(""); -} +void DataLayout::init(const Module *M) { *this = M->getDataLayout(); } bool DataLayout::operator==(const DataLayout &Other) const { bool Ret = BigEndian == Other.BigEndian && @@ -381,16 +385,28 @@ bool DataLayout::operator==(const DataLayout &Other) const { ManglingMode == Other.ManglingMode && LegalIntWidths == Other.LegalIntWidths && Alignments == Other.Alignments && Pointers == Other.Pointers; - assert(Ret == (getStringRepresentation() == Other.getStringRepresentation())); + // Note: getStringRepresentation() might differs, it is not canonicalized return Ret; } void DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width) { - assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); - assert(pref_align < (1 << 16) && "Alignment doesn't fit in bitfield"); - assert(bit_width < (1 << 24) && "Bit width doesn't fit in bitfield"); + if (!isUInt<24>(bit_width)) + report_fatal_error("Invalid bit width, must be a 24bit integer"); + if (!isUInt<16>(abi_align)) + report_fatal_error("Invalid ABI alignment, must be a 16bit integer"); + if (!isUInt<16>(pref_align)) + report_fatal_error("Invalid preferred alignment, must be a 16bit integer"); + if (abi_align != 0 && !isPowerOf2_64(abi_align)) + report_fatal_error("Invalid ABI alignment, must be a power of 2"); + if (pref_align != 0 && !isPowerOf2_64(pref_align)) + report_fatal_error("Invalid preferred alignment, must be a power of 2"); + + if (pref_align < abi_align) + report_fatal_error( + "Preferred alignment cannot be less than the ABI alignment"); + for (LayoutAlignElem &Elem : Alignments) { if (Elem.AlignType == (unsigned)align_type && Elem.TypeBitWidth == bit_width) { @@ -416,7 +432,10 @@ DataLayout::findPointerLowerBound(uint32_t AddressSpace) { void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, unsigned PrefAlign, uint32_t TypeByteWidth) { - assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!"); + if (PrefAlign < ABIAlign) + report_fatal_error( + "Preferred alignment cannot be less than the ABI alignment"); + PointersTy::iterator I = findPointerLowerBound(AddrSpace); if (I == Pointers.end() || I->AddressSpace != AddrSpace) { Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign, @@ -463,9 +482,7 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, // If we didn't find an integer alignment, fall back on most conservative. if (AlignType == INTEGER_ALIGN) { BestMatchIdx = LargestInt; - } else { - assert(AlignType == VECTOR_ALIGN && "Unknown alignment type!"); - + } else if (AlignType == VECTOR_ALIGN) { // By default, use natural alignment for vector types. This is consistent // with what clang and llvm-gcc do. unsigned Align = getTypeAllocSize(cast<VectorType>(Ty)->getElementType()); @@ -478,6 +495,19 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, } } + // If we still couldn't find a reasonable default alignment, fall back + // to a simple heuristic that the alignment is the first power of two + // greater-or-equal to the store size of the type. This is a reasonable + // approximation of reality, and if the user wanted something less + // less conservative, they should have specified it explicitly in the data + // layout. + if (BestMatchIdx == -1) { + unsigned Align = getTypeStoreSize(Ty); + if (Align & (Align-1)) + Align = NextPowerOf2(Align); + return Align; + } + // Since we got a "best match" index, just return it. return ABIInfo ? Alignments[BestMatchIdx].ABIAlign : Alignments[BestMatchIdx].PrefAlign; @@ -541,68 +571,6 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const { return L; } -std::string DataLayout::getStringRepresentation() const { - std::string Result; - raw_string_ostream OS(Result); - - OS << (BigEndian ? "E" : "e"); - - switch (ManglingMode) { - case MM_None: - break; - case MM_ELF: - OS << "-m:e"; - break; - case MM_MachO: - OS << "-m:o"; - break; - case MM_WINCOFF: - OS << "-m:w"; - break; - case MM_Mips: - OS << "-m:m"; - break; - } - - for (const PointerAlignElem &PI : Pointers) { - // Skip default. - if (PI.AddressSpace == 0 && PI.ABIAlign == 8 && PI.PrefAlign == 8 && - PI.TypeByteWidth == 8) - continue; - - OS << "-p"; - if (PI.AddressSpace) { - OS << PI.AddressSpace; - } - OS << ":" << PI.TypeByteWidth*8 << ':' << PI.ABIAlign*8; - if (PI.PrefAlign != PI.ABIAlign) - OS << ':' << PI.PrefAlign*8; - } - - for (const LayoutAlignElem &AI : Alignments) { - if (std::find(std::begin(DefaultAlignments), std::end(DefaultAlignments), - AI) != std::end(DefaultAlignments)) - continue; - OS << '-' << (char)AI.AlignType; - if (AI.TypeBitWidth) - OS << AI.TypeBitWidth; - OS << ':' << AI.ABIAlign*8; - if (AI.ABIAlign != AI.PrefAlign) - OS << ':' << AI.PrefAlign*8; - } - - if (!LegalIntWidths.empty()) { - OS << "-n" << (unsigned)LegalIntWidths[0]; - - for (unsigned i = 1, e = LegalIntWidths.size(); i != e; ++i) - OS << ':' << (unsigned)LegalIntWidths[i]; - } - - if (StackNaturalAlign) - OS << "-S" << StackNaturalAlign*8; - - return OS.str(); -} unsigned DataLayout::getPointerABIAlignment(unsigned AS) const { PointersTy::const_iterator I = findPointerLowerBound(AS); @@ -818,18 +786,3 @@ unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const { return Log2_32(getPreferredAlignment(GV)); } -DataLayoutPass::DataLayoutPass() : ImmutablePass(ID), DL("") { - initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); -} - -DataLayoutPass::~DataLayoutPass() {} - -bool DataLayoutPass::doInitialization(Module &M) { - DL.init(&M); - return false; -} - -bool DataLayoutPass::doFinalization(Module &M) { - DL.reset(""); - return false; -} diff --git a/contrib/llvm/lib/IR/DebugInfo.cpp b/contrib/llvm/lib/IR/DebugInfo.cpp index 71b4394..2e161c2 100644 --- a/contrib/llvm/lib/IR/DebugInfo.cpp +++ b/contrib/llvm/lib/IR/DebugInfo.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/GVMaterializer.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" @@ -32,914 +33,62 @@ using namespace llvm; using namespace llvm::dwarf; -//===----------------------------------------------------------------------===// -// DIDescriptor -//===----------------------------------------------------------------------===// - -bool DIDescriptor::Verify() const { - return DbgNode && - (DIDerivedType(DbgNode).Verify() || - DICompositeType(DbgNode).Verify() || DIBasicType(DbgNode).Verify() || - DIVariable(DbgNode).Verify() || DISubprogram(DbgNode).Verify() || - DIGlobalVariable(DbgNode).Verify() || DIFile(DbgNode).Verify() || - DICompileUnit(DbgNode).Verify() || DINameSpace(DbgNode).Verify() || - DILexicalBlock(DbgNode).Verify() || - DILexicalBlockFile(DbgNode).Verify() || - DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() || - DIObjCProperty(DbgNode).Verify() || - DITemplateTypeParameter(DbgNode).Verify() || - DITemplateValueParameter(DbgNode).Verify() || - DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify()); -} - -static Metadata *getField(const MDNode *DbgNode, unsigned Elt) { - if (!DbgNode || Elt >= DbgNode->getNumOperands()) - return nullptr; - return DbgNode->getOperand(Elt); -} - -static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { - return dyn_cast_or_null<MDNode>(getField(DbgNode, Elt)); -} - -static StringRef getStringField(const MDNode *DbgNode, unsigned Elt) { - if (MDString *MDS = dyn_cast_or_null<MDString>(getField(DbgNode, Elt))) - return MDS->getString(); - return StringRef(); -} - -StringRef DIDescriptor::getStringField(unsigned Elt) const { - return ::getStringField(DbgNode, Elt); -} - -uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { - if (auto *C = getConstantField(Elt)) - if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) - return CI->getZExtValue(); - - return 0; -} - -int64_t DIDescriptor::getInt64Field(unsigned Elt) const { - if (auto *C = getConstantField(Elt)) - if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) - return CI->getZExtValue(); - - return 0; -} - -DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { - MDNode *Field = getNodeField(DbgNode, Elt); - return DIDescriptor(Field); -} - -GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { - return dyn_cast_or_null<GlobalVariable>(getConstantField(Elt)); -} - -Constant *DIDescriptor::getConstantField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - if (auto *C = - dyn_cast_or_null<ConstantAsMetadata>(DbgNode->getOperand(Elt))) - return C->getValue(); +DISubprogram *llvm::getDISubprogram(const MDNode *Scope) { + if (auto *LocalScope = dyn_cast_or_null<DILocalScope>(Scope)) + return LocalScope->getSubprogram(); return nullptr; } -Function *DIDescriptor::getFunctionField(unsigned Elt) const { - return dyn_cast_or_null<Function>(getConstantField(Elt)); -} - -void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { - if (!DbgNode) - return; - - if (Elt < DbgNode->getNumOperands()) { - MDNode *Node = const_cast<MDNode *>(DbgNode); - Node->replaceOperandWith(Elt, F ? ConstantAsMetadata::get(F) : nullptr); - } -} - -static unsigned DIVariableInlinedAtIndex = 4; -MDNode *DIVariable::getInlinedAt() const { - return getNodeField(DbgNode, DIVariableInlinedAtIndex); -} - -/// \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); -} - -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 -//===----------------------------------------------------------------------===// - -bool DIDescriptor::isSubroutineType() const { - return DbgNode && getTag() == dwarf::DW_TAG_subroutine_type; -} - -bool DIDescriptor::isBasicType() const { - if (!DbgNode) - return false; - switch (getTag()) { - case dwarf::DW_TAG_base_type: - case dwarf::DW_TAG_unspecified_type: - return true; - default: - return false; - } -} - -bool DIDescriptor::isDerivedType() const { - if (!DbgNode) - return false; - switch (getTag()) { - case dwarf::DW_TAG_typedef: - case dwarf::DW_TAG_pointer_type: - case dwarf::DW_TAG_ptr_to_member_type: - case dwarf::DW_TAG_reference_type: - case dwarf::DW_TAG_rvalue_reference_type: - case dwarf::DW_TAG_const_type: - case dwarf::DW_TAG_volatile_type: - case dwarf::DW_TAG_restrict_type: - case dwarf::DW_TAG_member: - case dwarf::DW_TAG_inheritance: - case dwarf::DW_TAG_friend: - return true; - default: - // CompositeTypes are currently modelled as DerivedTypes. - return isCompositeType(); - } -} - -bool DIDescriptor::isCompositeType() const { - if (!DbgNode) - return false; - switch (getTag()) { - case dwarf::DW_TAG_array_type: - case dwarf::DW_TAG_structure_type: - case dwarf::DW_TAG_union_type: - case dwarf::DW_TAG_enumeration_type: - case dwarf::DW_TAG_subroutine_type: - case dwarf::DW_TAG_class_type: - return true; - default: - return false; - } -} - -bool DIDescriptor::isVariable() const { - if (!DbgNode) - return false; - switch (getTag()) { - case dwarf::DW_TAG_auto_variable: - case dwarf::DW_TAG_arg_variable: - return true; - default: - return false; - } -} - -bool DIDescriptor::isType() const { - return isBasicType() || isCompositeType() || isDerivedType(); -} - -bool DIDescriptor::isSubprogram() const { - return DbgNode && getTag() == dwarf::DW_TAG_subprogram; -} - -bool DIDescriptor::isGlobalVariable() const { - return DbgNode && (getTag() == dwarf::DW_TAG_variable || - getTag() == dwarf::DW_TAG_constant); -} - -bool DIDescriptor::isScope() const { - if (!DbgNode) - return false; - switch (getTag()) { - case dwarf::DW_TAG_compile_unit: - case dwarf::DW_TAG_lexical_block: - case dwarf::DW_TAG_subprogram: - case dwarf::DW_TAG_namespace: - case dwarf::DW_TAG_file_type: - return true; - default: - break; - } - return isType(); -} - -bool DIDescriptor::isTemplateTypeParameter() const { - return DbgNode && getTag() == dwarf::DW_TAG_template_type_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); -} - -bool DIDescriptor::isCompileUnit() const { - return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; -} - -bool DIDescriptor::isFile() const { - return DbgNode && getTag() == dwarf::DW_TAG_file_type; -} - -bool DIDescriptor::isNameSpace() const { - return DbgNode && getTag() == dwarf::DW_TAG_namespace; -} - -bool DIDescriptor::isLexicalBlockFile() const { - return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && - DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 2; -} - -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 && - (getNumHeaderFields() == 2 || getNumHeaderFields() == 4); -} - -bool DIDescriptor::isSubrange() const { - return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; -} - -bool DIDescriptor::isEnumerator() const { - return DbgNode && getTag() == dwarf::DW_TAG_enumerator; -} - -bool DIDescriptor::isObjCProperty() const { - return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; -} - -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 -//===----------------------------------------------------------------------===// - -void DIDescriptor::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { - - assert(DbgNode && "Trying to replace an unverified type!"); - - // Since we use a TrackingVH for the node, its easy for clients to manufacture - // legitimate situations where they want to replaceAllUsesWith() on something - // which, due to uniquing, has merged with the source. We shield clients from - // this detail by allowing a value to be replaced with replaceAllUsesWith() - // itself. - const MDNode *DN = D; - if (DbgNode == DN) { - SmallVector<Metadata *, 10> Ops(DbgNode->getNumOperands()); - for (size_t i = 0; i != Ops.size(); ++i) - Ops[i] = DbgNode->getOperand(i); - DN = MDNode::get(VMContext, Ops); - } - - auto *Node = cast<MDNodeFwdDecl>(const_cast<MDNode *>(DbgNode)); - Node->replaceAllUsesWith(const_cast<MDNode *>(DN)); - MDNode::deleteTemporary(Node); - DbgNode = DN; -} - -void DIDescriptor::replaceAllUsesWith(MDNode *D) { - assert(DbgNode && "Trying to replace an unverified type!"); - assert(DbgNode != D && "This replacement should always happen"); - auto *Node = cast<MDNodeFwdDecl>(const_cast<MDNode *>(DbgNode)); - Node->replaceAllUsesWith(D); - MDNode::deleteTemporary(Node); -} - -bool DICompileUnit::Verify() const { - if (!isCompileUnit()) - return false; - - // Don't bother verifying the compilation directory or producer string - // as those could be empty. - if (getFilename().empty()) - return false; - - return DbgNode->getNumOperands() == 7 && getNumHeaderFields() == 8; -} - -bool DIObjCProperty::Verify() const { - if (!isObjCProperty()) - return false; - - // Don't worry about the rest of the strings for now. - return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 6; -} - -/// \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) { - // FIXME: This function should return true, if the field is null or the field - // is indeed a MDNode: return !Fld || isa<MDNode>(Fld). - Metadata *Fld = getField(DbgNode, Elt); - if (Fld && isa<MDString>(Fld) && !cast<MDString>(Fld)->getString().empty()) - return false; - return true; -} - -/// \brief Check if a field at position Elt of a MDNode is a MDString. -static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) { - Metadata *Fld = getField(DbgNode, Elt); - return !Fld || isa<MDString>(Fld); -} - -/// \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; -} - -/// \brief Check if referenced field might be a type. -static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) { - return isTypeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt))); -} - -/// \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); -} - -/// \brief Check if a field at position Elt of a MDNode can be a ScopeRef. -static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) { - return isScopeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt))); -} - -bool DIType::Verify() const { - if (!isType()) - return false; - // Make sure Context @ field 2 is MDNode. - if (!fieldIsScopeRef(DbgNode, 2)) - return false; - - // FIXME: Sink this into the various subclass verifies. - uint16_t Tag = getTag(); - if (!isBasicType() && Tag != dwarf::DW_TAG_const_type && - Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type && - Tag != dwarf::DW_TAG_ptr_to_member_type && - Tag != dwarf::DW_TAG_reference_type && - Tag != dwarf::DW_TAG_rvalue_reference_type && - Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_array_type && - Tag != dwarf::DW_TAG_enumeration_type && - Tag != dwarf::DW_TAG_subroutine_type && - Tag != dwarf::DW_TAG_inheritance && Tag != dwarf::DW_TAG_friend && - getFilename().empty()) - return false; - - // DIType is abstract, it should be a BasicType, a DerivedType or - // a CompositeType. - if (isBasicType()) - return DIBasicType(DbgNode).Verify(); - else if (isCompositeType()) - return DICompositeType(DbgNode).Verify(); - else if (isDerivedType()) - return DIDerivedType(DbgNode).Verify(); - else - return false; -} - -bool DIBasicType::Verify() const { - return isBasicType() && DbgNode->getNumOperands() == 3 && - getNumHeaderFields() == 8; -} - -bool DIDerivedType::Verify() const { - // 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 4 is a TypeRef. - if (!fieldIsTypeRef(DbgNode, 4)) - return false; - - return isDerivedType() && DbgNode->getNumOperands() >= 4 && - DbgNode->getNumOperands() <= 8 && getNumHeaderFields() >= 7 && - getNumHeaderFields() <= 8; -} - -bool DICompositeType::Verify() const { - if (!isCompositeType()) - return false; - - // Make sure DerivedFrom @ field 3 and ContainingType @ field 5 are TypeRef. - if (!fieldIsTypeRef(DbgNode, 3)) - return false; - if (!fieldIsTypeRef(DbgNode, 5)) - return false; - - // 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() == 8 && getNumHeaderFields() == 8; -} - -bool DISubprogram::Verify() const { - if (!isSubprogram()) - return false; - - // Make sure context @ field 2 is a ScopeRef and type @ field 3 is a MDNode. - if (!fieldIsScopeRef(DbgNode, 2)) - return false; - if (!fieldIsMDNode(DbgNode, 3)) - return false; - // Containing type @ field 4. - if (!fieldIsTypeRef(DbgNode, 4)) - return false; - - // A subprogram can't be both & and &&. - if (isLValueReference() && isRValueReference()) - return false; - - // 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()) { - 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 ((IA = DL.getInlinedAt())) - DL = DebugLoc::getFromDILocation(IA); - DL.getScopeAndInlinedAt(Scope, IA); - if (!Scope) - return false; - assert(!IA); - while (!DIDescriptor(Scope).isSubprogram()) { - DILexicalBlockFile D(Scope); - Scope = D.isLexicalBlockFile() - ? D.getScope() - : DebugLoc::getFromDILexicalBlock(Scope).getScope(); - assert(Scope && "lexical block file has no scope"); - } - if (!DISubprogram(Scope).describes(F)) - return false; - } - } - } - return DbgNode->getNumOperands() == 9 && getNumHeaderFields() == 12; -} - -bool DIGlobalVariable::Verify() const { - if (!isGlobalVariable()) - return false; - - if (getDisplayName().empty()) - return false; - // Make sure context @ field 1 is an MDNode. - if (!fieldIsMDNode(DbgNode, 1)) - return false; - // Make sure that type @ field 3 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 3)) - return false; - // Make sure StaticDataMemberDeclaration @ field 5 is MDNode. - if (!fieldIsMDNode(DbgNode, 5)) - return false; - - return DbgNode->getNumOperands() == 6 && getNumHeaderFields() == 7; -} - -bool DIVariable::Verify() const { - if (!isVariable()) - return false; - - // Make sure context @ field 1 is an MDNode. - if (!fieldIsMDNode(DbgNode, 1)) - return false; - // Make sure that type @ field 3 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 3)) - return false; - - // 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; - - return isExpression() && DbgNode->getNumOperands() == 1; -} - -bool DILocation::Verify() const { - return DbgNode && isa<MDLocation>(DbgNode); -} - -bool DINameSpace::Verify() const { - if (!isNameSpace()) - return false; - return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 3; -} - -MDNode *DIFile::getFileNode() const { return getNodeField(DbgNode, 1); } - -bool DIFile::Verify() const { - return isFile() && DbgNode->getNumOperands() == 2; -} - -bool DIEnumerator::Verify() const { - return isEnumerator() && DbgNode->getNumOperands() == 1 && - getNumHeaderFields() == 3; -} - -bool DISubrange::Verify() const { - return isSubrange() && DbgNode->getNumOperands() == 1 && - getNumHeaderFields() == 3; -} - -bool DILexicalBlock::Verify() const { - return isLexicalBlock() && DbgNode->getNumOperands() == 3 && - getNumHeaderFields() == 4; -} - -bool DILexicalBlockFile::Verify() const { - return isLexicalBlockFile() && DbgNode->getNumOperands() == 3 && - getNumHeaderFields() == 2; -} - -bool DITemplateTypeParameter::Verify() const { - return isTemplateTypeParameter() && DbgNode->getNumOperands() == 4 && - getNumHeaderFields() == 4; -} - -bool DITemplateValueParameter::Verify() const { - return isTemplateValueParameter() && DbgNode->getNumOperands() == 5 && - getNumHeaderFields() == 4; -} - -bool DIImportedEntity::Verify() const { - return isImportedEntity() && DbgNode->getNumOperands() == 3 && - getNumHeaderFields() == 3; -} - -MDNode *DIDerivedType::getObjCProperty() const { - return getNodeField(DbgNode, 4); -} - -MDString *DICompositeType::getIdentifier() const { - return cast_or_null<MDString>(getField(DbgNode, 7)); -} - -#ifndef NDEBUG -static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) { - for (unsigned i = 0; i != LHS->getNumOperands(); ++i) { - // Skip the 'empty' list (that's a single i32 0, rather than truly empty). - if (i == 0 && mdconst::hasa<ConstantInt>(LHS->getOperand(i))) - continue; - const MDNode *E = cast<MDNode>(LHS->getOperand(i)); - bool found = false; - for (unsigned j = 0; !found && j != RHS->getNumOperands(); ++j) - found = (E == cast<MDNode>(RHS->getOperand(j))); - assert(found && "Losing a member during member list replacement"); - } -} -#endif - -void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) { - TrackingMDNodeRef 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(4))) - VerifySubsetOf(El, Elements); -#endif - N->replaceOperandWith(4, Elements); - } - if (TParams) - N->replaceOperandWith(6, TParams); - DbgNode = N; -} - -DIScopeRef DIScope::getRef() const { - if (!isCompositeType()) - return DIScopeRef(*this); - DICompositeType DTy(DbgNode); - if (!DTy.getIdentifier()) - return DIScopeRef(*this); - return DIScopeRef(DTy.getIdentifier()); -} - -void DICompositeType::setContainingType(DICompositeType ContainingType) { - TrackingMDNodeRef N(*this); - N->replaceOperandWith(5, ContainingType.getRef()); - DbgNode = N; -} - -bool DIVariable::isInlinedFnArgument(const Function *CurFn) { - assert(CurFn && "Invalid function"); - if (!getContext().isSubprogram()) - return false; - // This variable is not inlined function argument if its scope - // does not describe current function. - return !DISubprogram(getContext()).describes(CurFn); -} - -bool DISubprogram::describes(const Function *F) { - assert(F && "Invalid function"); - if (F == getFunction()) - return true; - StringRef Name = getLinkageName(); - if (Name.empty()) - Name = getName(); - if (F->getName() == Name) - return true; - return false; -} - -MDNode *DISubprogram::getVariablesNodes() const { - return getNodeField(DbgNode, 8); -} - -DIArray DISubprogram::getVariables() const { - return DIArray(getNodeField(DbgNode, 8)); -} - -Metadata *DITemplateValueParameter::getValue() const { - return DbgNode->getOperand(3); -} - -DIScopeRef DIScope::getContext() const { - - if (isType()) - return DIType(DbgNode).getContext(); - - if (isSubprogram()) - return DIScopeRef(DISubprogram(DbgNode).getContext()); - - if (isLexicalBlock()) - return DIScopeRef(DILexicalBlock(DbgNode).getContext()); - - if (isLexicalBlockFile()) - return DIScopeRef(DILexicalBlockFile(DbgNode).getContext()); - - if (isNameSpace()) - return DIScopeRef(DINameSpace(DbgNode).getContext()); - - assert((isFile() || isCompileUnit()) && "Unhandled type of scope."); - return DIScopeRef(nullptr); -} - -StringRef DIScope::getName() const { - if (isType()) - return DIType(DbgNode).getName(); - if (isSubprogram()) - return DISubprogram(DbgNode).getName(); - if (isNameSpace()) - return DINameSpace(DbgNode).getName(); - assert((isLexicalBlock() || isLexicalBlockFile() || isFile() || - isCompileUnit()) && - "Unhandled type of scope."); - return StringRef(); -} - -StringRef DIScope::getFilename() const { - if (!DbgNode) - return StringRef(); - return ::getStringField(getNodeField(DbgNode, 1), 0); -} - -StringRef DIScope::getDirectory() const { - if (!DbgNode) - return StringRef(); - return ::getStringField(getNodeField(DbgNode, 1), 1); -} - -DIArray DICompileUnit::getEnumTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 7) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 2)); -} - -DIArray DICompileUnit::getRetainedTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 7) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 3)); -} - -DIArray DICompileUnit::getSubprograms() const { - if (!DbgNode || DbgNode->getNumOperands() < 7) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 4)); -} - -DIArray DICompileUnit::getGlobalVariables() const { - if (!DbgNode || DbgNode->getNumOperands() < 7) - return DIArray(); - - return DIArray(getNodeField(DbgNode, 5)); -} - -DIArray DICompileUnit::getImportedEntities() const { - if (!DbgNode || DbgNode->getNumOperands() < 7) - return DIArray(); - - 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); -} - -DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, - DILexicalBlockFile NewScope) { - assert(Verify()); - assert(NewScope && "Expected valid scope"); - - const auto *Old = cast<MDLocation>(DbgNode); - return DILocation(MDLocation::get(Ctx, Old->getLine(), Old->getColumn(), - NewScope, Old->getInlinedAt())); -} - -unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) { - std::pair<const char *, unsigned> Key(getFilename().data(), getLineNumber()); - return ++Ctx.pImpl->DiscriminatorTable[Key]; -} - -DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext) { - assert(DIVariable(DV).Verify() && "Expected a DIVariable"); - if (!InlinedScope) - return cleanseInlinedVariable(DV, VMContext); - - // Insert inlined scope. - SmallVector<Metadata *, 8> Elts; - for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) - Elts.push_back(DV->getOperand(I)); - Elts.push_back(InlinedScope); - - DIVariable Inlined(MDNode::get(VMContext, Elts)); - assert(Inlined.Verify() && "Expected to create a DIVariable"); - return Inlined; -} - -DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { - assert(DIVariable(DV).Verify() && "Expected a DIVariable"); - if (!DIVariable(DV).getInlinedAt()) - return DIVariable(DV); - - // Remove inlined scope. - SmallVector<Metadata *, 8> Elts; - for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) - Elts.push_back(DV->getOperand(I)); - - DIVariable Cleansed(MDNode::get(VMContext, Elts)); - assert(Cleansed.Verify() && "Expected to create a DIVariable"); - return Cleansed; -} - -DISubprogram llvm::getDISubprogram(const MDNode *Scope) { - DIDescriptor D(Scope); - if (D.isSubprogram()) - return DISubprogram(Scope); - - if (D.isLexicalBlockFile()) - return getDISubprogram(DILexicalBlockFile(Scope).getContext()); - - if (D.isLexicalBlock()) - return getDISubprogram(DILexicalBlock(Scope).getContext()); - - return DISubprogram(); -} - -DISubprogram llvm::getDISubprogram(const Function *F) { +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(); + return Inst.getDebugLoc(); }); if (Inst == BB.end()) continue; DebugLoc DLoc = Inst->getDebugLoc(); - const MDNode *Scope = DLoc.getScopeNode(); - DISubprogram Subprogram = getDISubprogram(Scope); - return Subprogram.describes(F) ? Subprogram : DISubprogram(); + const MDNode *Scope = DLoc.getInlinedAtScope(); + auto *Subprogram = getDISubprogram(Scope); + return Subprogram->describes(F) ? Subprogram : nullptr; } - return DISubprogram(); + return nullptr; } -DICompositeType llvm::getDICompositeType(DIType T) { - if (T.isCompositeType()) - return DICompositeType(T); +DICompositeTypeBase *llvm::getDICompositeType(DIType *T) { + if (auto *C = dyn_cast_or_null<DICompositeTypeBase>(T)) + return C; - if (T.isDerivedType()) { + if (auto *D = dyn_cast_or_null<DIDerivedTypeBase>(T)) { // This function is currently used by dragonegg and dragonegg does // not generate identifier for types, so using an empty map to resolve // DerivedFrom should be fine. DITypeIdentifierMap EmptyMap; - return getDICompositeType( - DIDerivedType(T).getTypeDerivedFrom().resolve(EmptyMap)); + return getDICompositeType(D->getBaseType().resolve(EmptyMap)); } - return DICompositeType(); + return nullptr; } DITypeIdentifierMap llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) { DITypeIdentifierMap Map; for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) { - DICompileUnit CU(CU_Nodes->getOperand(CUi)); - DIArray Retain = CU.getRetainedTypes(); - for (unsigned Ti = 0, Te = Retain.getNumElements(); Ti != Te; ++Ti) { - if (!Retain.getElement(Ti).isCompositeType()) + auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(CUi)); + DINodeArray Retain = CU->getRetainedTypes(); + for (unsigned Ti = 0, Te = Retain.size(); Ti != Te; ++Ti) { + if (!isa<DICompositeType>(Retain[Ti])) continue; - DICompositeType Ty(Retain.getElement(Ti)); - if (MDString *TypeId = Ty.getIdentifier()) { + auto *Ty = cast<DICompositeType>(Retain[Ti]); + if (MDString *TypeId = Ty->getRawIdentifier()) { // Definition has priority over declaration. // Try to insert (TypeId, Ty) to Map. std::pair<DITypeIdentifierMap::iterator, bool> P = Map.insert(std::make_pair(TypeId, Ty)); // If TypeId already exists in Map and this is a definition, replace // whatever we had (declaration or definition) with the definition. - if (!P.second && !Ty.isForwardDecl()) + if (!P.second && !Ty->isForwardDecl()) P.first->second = Ty; } } @@ -974,168 +123,146 @@ void DebugInfoFinder::processModule(const Module &M) { InitializeTypeMap(M); if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { - DICompileUnit CU(CU_Nodes->getOperand(i)); + auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); addCompileUnit(CU); - DIArray GVs = CU.getGlobalVariables(); - for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { - DIGlobalVariable DIG(GVs.getElement(i)); + for (auto *DIG : CU->getGlobalVariables()) { if (addGlobalVariable(DIG)) { - processScope(DIG.getContext()); - processType(DIG.getType().resolve(TypeIdentifierMap)); + processScope(DIG->getScope()); + processType(DIG->getType().resolve(TypeIdentifierMap)); } } - DIArray SPs = CU.getSubprograms(); - for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) - processSubprogram(DISubprogram(SPs.getElement(i))); - DIArray EnumTypes = CU.getEnumTypes(); - for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) - processType(DIType(EnumTypes.getElement(i))); - DIArray RetainedTypes = CU.getRetainedTypes(); - for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) - processType(DIType(RetainedTypes.getElement(i))); - DIArray Imports = CU.getImportedEntities(); - for (unsigned i = 0, e = Imports.getNumElements(); i != e; ++i) { - DIImportedEntity Import = DIImportedEntity(Imports.getElement(i)); - DIDescriptor Entity = Import.getEntity().resolve(TypeIdentifierMap); - if (Entity.isType()) - processType(DIType(Entity)); - else if (Entity.isSubprogram()) - processSubprogram(DISubprogram(Entity)); - else if (Entity.isNameSpace()) - processScope(DINameSpace(Entity).getContext()); + for (auto *SP : CU->getSubprograms()) + processSubprogram(SP); + for (auto *ET : CU->getEnumTypes()) + processType(ET); + for (auto *RT : CU->getRetainedTypes()) + processType(RT); + for (auto *Import : CU->getImportedEntities()) { + auto *Entity = Import->getEntity().resolve(TypeIdentifierMap); + if (auto *T = dyn_cast<DIType>(Entity)) + processType(T); + else if (auto *SP = dyn_cast<DISubprogram>(Entity)) + processSubprogram(SP); + else if (auto *NS = dyn_cast<DINamespace>(Entity)) + processScope(NS->getScope()); } } } } -void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { +void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) { if (!Loc) return; InitializeTypeMap(M); - processScope(Loc.getScope()); - processLocation(M, Loc.getOrigLocation()); + processScope(Loc->getScope()); + processLocation(M, Loc->getInlinedAt()); } -void DebugInfoFinder::processType(DIType DT) { +void DebugInfoFinder::processType(DIType *DT) { if (!addType(DT)) return; - processScope(DT.getContext().resolve(TypeIdentifierMap)); - if (DT.isCompositeType()) { - DICompositeType DCT(DT); - processType(DCT.getTypeDerivedFrom().resolve(TypeIdentifierMap)); - if (DT.isSubroutineType()) { - DITypeArray DTA = DISubroutineType(DT).getTypeArray(); - for (unsigned i = 0, e = DTA.getNumElements(); i != e; ++i) - processType(DTA.getElement(i).resolve(TypeIdentifierMap)); + processScope(DT->getScope().resolve(TypeIdentifierMap)); + if (auto *DCT = dyn_cast<DICompositeTypeBase>(DT)) { + processType(DCT->getBaseType().resolve(TypeIdentifierMap)); + if (auto *ST = dyn_cast<DISubroutineType>(DCT)) { + for (DITypeRef Ref : ST->getTypeArray()) + processType(Ref.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()) - processType(DIType(D)); - else if (D.isSubprogram()) - processSubprogram(DISubprogram(D)); + for (Metadata *D : DCT->getElements()) { + if (auto *T = dyn_cast<DIType>(D)) + processType(T); + else if (auto *SP = dyn_cast<DISubprogram>(D)) + processSubprogram(SP); } - } else if (DT.isDerivedType()) { - DIDerivedType DDT(DT); - processType(DDT.getTypeDerivedFrom().resolve(TypeIdentifierMap)); + } else if (auto *DDT = dyn_cast<DIDerivedTypeBase>(DT)) { + processType(DDT->getBaseType().resolve(TypeIdentifierMap)); } } -void DebugInfoFinder::processScope(DIScope Scope) { - if (Scope.isType()) { - DIType Ty(Scope); +void DebugInfoFinder::processScope(DIScope *Scope) { + if (!Scope) + return; + if (auto *Ty = dyn_cast<DIType>(Scope)) { processType(Ty); return; } - if (Scope.isCompileUnit()) { - addCompileUnit(DICompileUnit(Scope)); + if (auto *CU = dyn_cast<DICompileUnit>(Scope)) { + addCompileUnit(CU); return; } - if (Scope.isSubprogram()) { - processSubprogram(DISubprogram(Scope)); + if (auto *SP = dyn_cast<DISubprogram>(Scope)) { + processSubprogram(SP); return; } if (!addScope(Scope)) return; - if (Scope.isLexicalBlock()) { - DILexicalBlock LB(Scope); - processScope(LB.getContext()); - } else if (Scope.isLexicalBlockFile()) { - DILexicalBlockFile LBF = DILexicalBlockFile(Scope); - processScope(LBF.getScope()); - } else if (Scope.isNameSpace()) { - DINameSpace NS(Scope); - processScope(NS.getContext()); + if (auto *LB = dyn_cast<DILexicalBlockBase>(Scope)) { + processScope(LB->getScope()); + } else if (auto *NS = dyn_cast<DINamespace>(Scope)) { + processScope(NS->getScope()); } } -void DebugInfoFinder::processSubprogram(DISubprogram SP) { +void DebugInfoFinder::processSubprogram(DISubprogram *SP) { if (!addSubprogram(SP)) return; - processScope(SP.getContext().resolve(TypeIdentifierMap)); - processType(SP.getType()); - DIArray TParams = SP.getTemplateParams(); - for (unsigned I = 0, E = TParams.getNumElements(); I != E; ++I) { - DIDescriptor Element = TParams.getElement(I); - if (Element.isTemplateTypeParameter()) { - DITemplateTypeParameter TType(Element); - processScope(TType.getContext().resolve(TypeIdentifierMap)); - processType(TType.getType().resolve(TypeIdentifierMap)); - } else if (Element.isTemplateValueParameter()) { - DITemplateValueParameter TVal(Element); - processScope(TVal.getContext().resolve(TypeIdentifierMap)); - processType(TVal.getType().resolve(TypeIdentifierMap)); + processScope(SP->getScope().resolve(TypeIdentifierMap)); + processType(SP->getType()); + for (auto *Element : SP->getTemplateParams()) { + if (auto *TType = dyn_cast<DITemplateTypeParameter>(Element)) { + processType(TType->getType().resolve(TypeIdentifierMap)); + } else if (auto *TVal = dyn_cast<DITemplateValueParameter>(Element)) { + processType(TVal->getType().resolve(TypeIdentifierMap)); } } } void DebugInfoFinder::processDeclare(const Module &M, const DbgDeclareInst *DDI) { - MDNode *N = dyn_cast<MDNode>(DDI->getVariable()); + auto *N = dyn_cast<MDNode>(DDI->getVariable()); if (!N) return; InitializeTypeMap(M); - DIDescriptor DV(N); - if (!DV.isVariable()) + auto *DV = dyn_cast<DILocalVariable>(N); + if (!DV) return; if (!NodesSeen.insert(DV).second) return; - processScope(DIVariable(N).getContext()); - processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); + processScope(DV->getScope()); + processType(DV->getType().resolve(TypeIdentifierMap)); } void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) { - MDNode *N = dyn_cast<MDNode>(DVI->getVariable()); + auto *N = dyn_cast<MDNode>(DVI->getVariable()); if (!N) return; InitializeTypeMap(M); - DIDescriptor DV(N); - if (!DV.isVariable()) + auto *DV = dyn_cast<DILocalVariable>(N); + if (!DV) return; if (!NodesSeen.insert(DV).second) return; - processScope(DIVariable(N).getContext()); - processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); + processScope(DV->getScope()); + processType(DV->getType().resolve(TypeIdentifierMap)); } -bool DebugInfoFinder::addType(DIType DT) { +bool DebugInfoFinder::addType(DIType *DT) { if (!DT) return false; if (!NodesSeen.insert(DT).second) return false; - TYs.push_back(DT); + TYs.push_back(const_cast<DIType *>(DT)); return true; } -bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { +bool DebugInfoFinder::addCompileUnit(DICompileUnit *CU) { if (!CU) return false; if (!NodesSeen.insert(CU).second) @@ -1145,7 +272,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { return true; } -bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { +bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable *DIG) { if (!DIG) return false; @@ -1156,7 +283,7 @@ bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { return true; } -bool DebugInfoFinder::addSubprogram(DISubprogram SP) { +bool DebugInfoFinder::addSubprogram(DISubprogram *SP) { if (!SP) return false; @@ -1167,7 +294,7 @@ bool DebugInfoFinder::addSubprogram(DISubprogram SP) { return true; } -bool DebugInfoFinder::addScope(DIScope Scope) { +bool DebugInfoFinder::addScope(DIScope *Scope) { if (!Scope) return false; // FIXME: Ocaml binding generates a scope with no content, we treat it @@ -1180,284 +307,17 @@ bool DebugInfoFinder::addScope(DIScope Scope) { return true; } -//===----------------------------------------------------------------------===// -// DIDescriptor: dump routines for all descriptors. -//===----------------------------------------------------------------------===// - -void DIDescriptor::dump() const { - print(dbgs()); - dbgs() << '\n'; -} - -void DIDescriptor::print(raw_ostream &OS) const { - if (!DbgNode) - return; - - if (const char *Tag = dwarf::TagString(getTag())) - OS << "[ " << Tag << " ]"; - - if (this->isSubrange()) { - DISubrange(DbgNode).printInternal(OS); - } else if (this->isCompileUnit()) { - DICompileUnit(DbgNode).printInternal(OS); - } else if (this->isFile()) { - DIFile(DbgNode).printInternal(OS); - } else if (this->isEnumerator()) { - DIEnumerator(DbgNode).printInternal(OS); - } else if (this->isBasicType()) { - DIType(DbgNode).printInternal(OS); - } else if (this->isDerivedType()) { - DIDerivedType(DbgNode).printInternal(OS); - } else if (this->isCompositeType()) { - DICompositeType(DbgNode).printInternal(OS); - } else if (this->isSubprogram()) { - DISubprogram(DbgNode).printInternal(OS); - } else if (this->isGlobalVariable()) { - DIGlobalVariable(DbgNode).printInternal(OS); - } else if (this->isVariable()) { - DIVariable(DbgNode).printInternal(OS); - } else if (this->isObjCProperty()) { - DIObjCProperty(DbgNode).printInternal(OS); - } else if (this->isNameSpace()) { - DINameSpace(DbgNode).printInternal(OS); - } else if (this->isScope()) { - DIScope(DbgNode).printInternal(OS); - } else if (this->isExpression()) { - DIExpression(DbgNode).printInternal(OS); - } -} - -void DISubrange::printInternal(raw_ostream &OS) const { - int64_t Count = getCount(); - if (Count != -1) - OS << " [" << getLo() << ", " << Count - 1 << ']'; - else - OS << " [unbounded]"; -} - -void DIScope::printInternal(raw_ostream &OS) const { - OS << " [" << getDirectory() << "/" << getFilename() << ']'; -} - -void DICompileUnit::printInternal(raw_ostream &OS) const { - DIScope::printInternal(OS); - OS << " ["; - unsigned Lang = getLanguage(); - if (const char *LangStr = dwarf::LanguageString(Lang)) - OS << LangStr; - else - (OS << "lang 0x").write_hex(Lang); - OS << ']'; -} - -void DIEnumerator::printInternal(raw_ostream &OS) const { - OS << " [" << getName() << " :: " << getEnumValue() << ']'; -} - -void DIType::printInternal(raw_ostream &OS) const { - if (!DbgNode) - return; - - StringRef Res = getName(); - if (!Res.empty()) - OS << " [" << Res << "]"; - - // TODO: Print context? - - OS << " [line " << getLineNumber() << ", size " << getSizeInBits() - << ", align " << getAlignInBits() << ", offset " << getOffsetInBits(); - if (isBasicType()) - if (const char *Enc = - dwarf::AttributeEncodingString(DIBasicType(DbgNode).getEncoding())) - OS << ", enc " << Enc; - OS << "]"; - - if (isPrivate()) - OS << " [private]"; - else if (isProtected()) - OS << " [protected]"; - else if (isPublic()) - OS << " [public]"; - - if (isArtificial()) - OS << " [artificial]"; - - if (isForwardDecl()) - OS << " [decl]"; - else if (getTag() == dwarf::DW_TAG_structure_type || - getTag() == dwarf::DW_TAG_union_type || - getTag() == dwarf::DW_TAG_enumeration_type || - getTag() == dwarf::DW_TAG_class_type) - OS << " [def]"; - if (isVector()) - OS << " [vector]"; - if (isStaticMember()) - OS << " [static]"; - - if (isLValueReference()) - OS << " [reference]"; - - if (isRValueReference()) - OS << " [rvalue reference]"; -} - -void DIDerivedType::printInternal(raw_ostream &OS) const { - DIType::printInternal(OS); - OS << " [from " << getTypeDerivedFrom().getName() << ']'; -} - -void DICompositeType::printInternal(raw_ostream &OS) const { - DIType::printInternal(OS); - DIArray A = getElements(); - OS << " [" << A.getNumElements() << " elements]"; -} - -void DINameSpace::printInternal(raw_ostream &OS) const { - StringRef Name = getName(); - if (!Name.empty()) - OS << " [" << Name << ']'; - - OS << " [line " << getLineNumber() << ']'; -} - -void DISubprogram::printInternal(raw_ostream &OS) const { - // TODO : Print context - OS << " [line " << getLineNumber() << ']'; - - if (isLocalToUnit()) - OS << " [local]"; - - if (isDefinition()) - OS << " [def]"; - - if (getScopeLineNumber() != getLineNumber()) - OS << " [scope " << getScopeLineNumber() << "]"; - - if (isPrivate()) - OS << " [private]"; - else if (isProtected()) - OS << " [protected]"; - else if (isPublic()) - OS << " [public]"; - - if (isLValueReference()) - OS << " [reference]"; - - if (isRValueReference()) - OS << " [rvalue reference]"; - - StringRef Res = getName(); - if (!Res.empty()) - OS << " [" << Res << ']'; -} - -void DIGlobalVariable::printInternal(raw_ostream &OS) const { - StringRef Res = getName(); - if (!Res.empty()) - OS << " [" << Res << ']'; - - OS << " [line " << getLineNumber() << ']'; - - // TODO : Print context - - if (isLocalToUnit()) - OS << " [local]"; - - if (isDefinition()) - OS << " [def]"; -} - -void DIVariable::printInternal(raw_ostream &OS) const { - StringRef Res = getName(); - if (!Res.empty()) - OS << " [" << Res << ']'; - - 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; - } - case DW_OP_deref: - // No arguments. - 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()) - OS << " [" << Name << ']'; - - OS << " [line " << getLineNumber() << ", properties " << getUnsignedField(6) - << ']'; -} - -static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, - const LLVMContext &Ctx) { - if (!DL.isUnknown()) { // Print source line info. - DIScope Scope(DL.getScope(Ctx)); - assert(Scope.isScope() && "Scope of a DebugLoc should be a DIScope."); - // Omit the directory, because it's likely to be long and uninteresting. - CommentOS << Scope.getFilename(); - CommentOS << ':' << DL.getLine(); - if (DL.getCol() != 0) - CommentOS << ':' << DL.getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); - if (!InlinedAtDL.isUnknown()) { - CommentOS << " @[ "; - printDebugLoc(InlinedAtDL, CommentOS, Ctx); - CommentOS << " ]"; - } - } -} - -void DIVariable::printExtendedName(raw_ostream &OS) const { - const LLVMContext &Ctx = DbgNode->getContext(); - StringRef Res = getName(); - if (!Res.empty()) - OS << Res << "," << getLineNumber(); - if (MDNode *InlinedAt = getInlinedAt()) { - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); - if (!InlinedAtDL.isUnknown()) { - OS << " @["; - printDebugLoc(InlinedAtDL, OS, Ctx); - OS << "]"; +bool llvm::stripDebugInfo(Function &F) { + bool Changed = false; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (I.getDebugLoc()) { + Changed = true; + I.setDebugLoc(DebugLoc()); + } } } -} - -template <> DIRef<DIScope>::DIRef(const Metadata *V) : Val(V) { - assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode"); -} -template <> DIRef<DIType>::DIRef(const Metadata *V) : Val(V) { - assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode"); -} - -template <> -DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const { - return DIScopeRef(cast_or_null<Metadata>(getField(DbgNode, Elt))); -} -template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const { - return DITypeRef(cast_or_null<Metadata>(getField(DbgNode, Elt))); + return Changed; } bool llvm::StripDebugInfo(Module &M) { @@ -1493,41 +353,34 @@ bool llvm::StripDebugInfo(Module &M) { } } - for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) - for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; - ++FI) - for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; - ++BI) { - if (!BI->getDebugLoc().isUnknown()) { - Changed = true; - BI->setDebugLoc(DebugLoc()); - } - } + for (Function &F : M) + Changed |= stripDebugInfo(F); + + if (GVMaterializer *Materializer = M.getMaterializer()) + Materializer->setStripDebugInfo(); return Changed; } unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { - if (auto *Val = mdconst::extract_or_null<ConstantInt>( + if (auto *Val = mdconst::dyn_extract_or_null<ConstantInt>( M.getModuleFlag("Debug Info Version"))) return Val->getZExtValue(); return 0; } -llvm::DenseMap<const llvm::Function *, llvm::DISubprogram> +DenseMap<const llvm::Function *, DISubprogram *> llvm::makeSubprogramMap(const Module &M) { - DenseMap<const Function *, DISubprogram> R; + DenseMap<const Function *, DISubprogram *> R; NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return R; for (MDNode *N : CU_Nodes->operands()) { - DICompileUnit CUNode(N); - DIArray SPs = CUNode.getSubprograms(); - for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { - DISubprogram SP(SPs.getElement(i)); - if (Function *F = SP.getFunction()) + auto *CUNode = cast<DICompileUnit>(N); + for (auto *SP : CUNode->getSubprograms()) { + if (Function *F = SP->getFunction()) R.insert(std::make_pair(F, SP)); } } diff --git a/contrib/llvm/lib/IR/DebugInfoMetadata.cpp b/contrib/llvm/lib/IR/DebugInfoMetadata.cpp new file mode 100644 index 0000000..8b9857d --- /dev/null +++ b/contrib/llvm/lib/IR/DebugInfoMetadata.cpp @@ -0,0 +1,551 @@ +//===- DebugInfoMetadata.cpp - Implement debug info metadata --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the debug info Metadata classes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DebugInfoMetadata.h" +#include "LLVMContextImpl.h" +#include "MetadataImpl.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/IR/Function.h" + +using namespace llvm; + +DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef<Metadata *> MDs) + : MDNode(C, DILocationKind, Storage, MDs) { + assert((MDs.size() == 1 || MDs.size() == 2) && + "Expected a scope and optional inlined-at"); + + // Set line and column. + assert(Column < (1u << 16) && "Expected 16-bit column"); + + SubclassData32 = Line; + SubclassData16 = Column; +} + +static void adjustColumn(unsigned &Column) { + // Set to unknown on overflow. We only have 16 bits to play with here. + if (Column >= (1u << 16)) + Column = 0; +} + +DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate) { + // Fixup column. + adjustColumn(Column); + + assert(Scope && "Expected scope"); + if (Storage == Uniqued) { + if (auto *N = + getUniqued(Context.pImpl->DILocations, + DILocationInfo::KeyTy(Line, Column, Scope, InlinedAt))) + return N; + if (!ShouldCreate) + return nullptr; + } else { + assert(ShouldCreate && "Expected non-uniqued nodes to always be created"); + } + + SmallVector<Metadata *, 2> Ops; + Ops.push_back(Scope); + if (InlinedAt) + Ops.push_back(InlinedAt); + return storeImpl(new (Ops.size()) + DILocation(Context, Storage, Line, Column, Ops), + Storage, Context.pImpl->DILocations); +} + +unsigned DILocation::computeNewDiscriminator() const { + // FIXME: This seems completely wrong. + // + // 1. If two modules are generated in the same context, then the second + // Module will get different discriminators than it would have if it were + // generated in its own context. + // 2. If this function is called after round-tripping to bitcode instead of + // before, it will give a different (and potentially incorrect!) return. + // + // The discriminator should instead be calculated from local information + // where it's actually needed. This logic should be moved to + // AddDiscriminators::runOnFunction(), where it doesn't pollute the + // LLVMContext. + std::pair<const char *, unsigned> Key(getFilename().data(), getLine()); + return ++getContext().pImpl->DiscriminatorTable[Key]; +} + +unsigned DINode::getFlag(StringRef Flag) { + return StringSwitch<unsigned>(Flag) +#define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME) +#include "llvm/IR/DebugInfoFlags.def" + .Default(0); +} + +const char *DINode::getFlagString(unsigned Flag) { + switch (Flag) { + default: + return ""; +#define HANDLE_DI_FLAG(ID, NAME) \ + case Flag##NAME: \ + return "DIFlag" #NAME; +#include "llvm/IR/DebugInfoFlags.def" + } +} + +unsigned DINode::splitFlags(unsigned Flags, + SmallVectorImpl<unsigned> &SplitFlags) { + // Accessibility flags need to be specially handled, since they're packed + // together. + if (unsigned A = Flags & FlagAccessibility) { + if (A == FlagPrivate) + SplitFlags.push_back(FlagPrivate); + else if (A == FlagProtected) + SplitFlags.push_back(FlagProtected); + else + SplitFlags.push_back(FlagPublic); + Flags &= ~A; + } + +#define HANDLE_DI_FLAG(ID, NAME) \ + if (unsigned Bit = Flags & ID) { \ + SplitFlags.push_back(Bit); \ + Flags &= ~Bit; \ + } +#include "llvm/IR/DebugInfoFlags.def" + + return Flags; +} + +DIScopeRef DIScope::getScope() const { + if (auto *T = dyn_cast<DIType>(this)) + return T->getScope(); + + if (auto *SP = dyn_cast<DISubprogram>(this)) + return SP->getScope(); + + if (auto *LB = dyn_cast<DILexicalBlockBase>(this)) + return DIScopeRef(LB->getScope()); + + if (auto *NS = dyn_cast<DINamespace>(this)) + return DIScopeRef(NS->getScope()); + + assert((isa<DIFile>(this) || isa<DICompileUnit>(this)) && + "Unhandled type of scope."); + return nullptr; +} + +StringRef DIScope::getName() const { + if (auto *T = dyn_cast<DIType>(this)) + return T->getName(); + if (auto *SP = dyn_cast<DISubprogram>(this)) + return SP->getName(); + if (auto *NS = dyn_cast<DINamespace>(this)) + return NS->getName(); + assert((isa<DILexicalBlockBase>(this) || isa<DIFile>(this) || + isa<DICompileUnit>(this)) && + "Unhandled type of scope."); + return ""; +} + +static StringRef getString(const MDString *S) { + if (S) + return S->getString(); + return StringRef(); +} + +#ifndef NDEBUG +static bool isCanonical(const MDString *S) { + return !S || !S->getString().empty(); +} +#endif + +GenericDINode *GenericDINode::getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, + ArrayRef<Metadata *> DwarfOps, + StorageType Storage, bool ShouldCreate) { + unsigned Hash = 0; + if (Storage == Uniqued) { + GenericDINodeInfo::KeyTy Key(Tag, getString(Header), DwarfOps); + if (auto *N = getUniqued(Context.pImpl->GenericDINodes, Key)) + return N; + if (!ShouldCreate) + return nullptr; + Hash = Key.getHash(); + } else { + assert(ShouldCreate && "Expected non-uniqued nodes to always be created"); + } + + // Use a nullptr for empty headers. + assert(isCanonical(Header) && "Expected canonical MDString"); + Metadata *PreOps[] = {Header}; + return storeImpl(new (DwarfOps.size() + 1) GenericDINode( + Context, Storage, Hash, Tag, PreOps, DwarfOps), + Storage, Context.pImpl->GenericDINodes); +} + +void GenericDINode::recalculateHash() { + setHash(GenericDINodeInfo::KeyTy::calculateHash(this)); +} + +#define UNWRAP_ARGS_IMPL(...) __VA_ARGS__ +#define UNWRAP_ARGS(ARGS) UNWRAP_ARGS_IMPL ARGS +#define DEFINE_GETIMPL_LOOKUP(CLASS, ARGS) \ + do { \ + if (Storage == Uniqued) { \ + if (auto *N = getUniqued(Context.pImpl->CLASS##s, \ + CLASS##Info::KeyTy(UNWRAP_ARGS(ARGS)))) \ + return N; \ + if (!ShouldCreate) \ + return nullptr; \ + } else { \ + assert(ShouldCreate && \ + "Expected non-uniqued nodes to always be created"); \ + } \ + } while (false) +#define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS) \ + return storeImpl(new (ArrayRef<Metadata *>(OPS).size()) \ + CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \ + Storage, Context.pImpl->CLASS##s) +#define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS) \ + return storeImpl(new (0u) CLASS(Context, Storage, UNWRAP_ARGS(ARGS)), \ + Storage, Context.pImpl->CLASS##s) +#define DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(CLASS, OPS) \ + return storeImpl(new (ArrayRef<Metadata *>(OPS).size()) \ + CLASS(Context, Storage, OPS), \ + Storage, Context.pImpl->CLASS##s) + +DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, + StorageType Storage, bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DISubrange, (Count, Lo)); + DEFINE_GETIMPL_STORE_NO_OPS(DISubrange, (Count, Lo)); +} + +DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, getString(Name))); + Metadata *Ops[] = {Name}; + DEFINE_GETIMPL_STORE(DIEnumerator, (Value), Ops); +} + +DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP( + DIBasicType, (Tag, getString(Name), SizeInBits, AlignInBits, Encoding)); + Metadata *Ops[] = {nullptr, nullptr, Name}; + DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding), + Ops); +} + +DIDerivedType *DIDerivedType::getImpl( + LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, getString(Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, ExtraData)); + Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData}; + DEFINE_GETIMPL_STORE( + DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags), + Ops); +} + +DICompositeType *DICompositeType::getImpl( + LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams, MDString *Identifier, StorageType Storage, + bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DICompositeType, + (Tag, getString(Name), File, Line, Scope, BaseType, + SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, + RuntimeLang, VTableHolder, TemplateParams, + getString(Identifier))); + Metadata *Ops[] = {File, Scope, Name, BaseType, + Elements, VTableHolder, TemplateParams, Identifier}; + DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, + AlignInBits, OffsetInBits, Flags), + Ops); +} + +DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, + unsigned Flags, Metadata *TypeArray, + StorageType Storage, + bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, TypeArray)); + Metadata *Ops[] = {nullptr, nullptr, nullptr, nullptr, + TypeArray, nullptr, nullptr, nullptr}; + DEFINE_GETIMPL_STORE(DISubroutineType, (Flags), Ops); +} + +DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate) { + assert(isCanonical(Filename) && "Expected canonical MDString"); + assert(isCanonical(Directory) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DIFile, (getString(Filename), getString(Directory))); + Metadata *Ops[] = {Filename, Directory}; + DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIFile, Ops); +} + +DICompileUnit *DICompileUnit::getImpl( + LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, uint64_t DWOId, + StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Producer) && "Expected canonical MDString"); + assert(isCanonical(Flags) && "Expected canonical MDString"); + assert(isCanonical(SplitDebugFilename) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP( + DICompileUnit, + (SourceLanguage, File, getString(Producer), IsOptimized, getString(Flags), + RuntimeVersion, getString(SplitDebugFilename), EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, ImportedEntities, DWOId)); + Metadata *Ops[] = {File, Producer, Flags, SplitDebugFilename, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities}; + DEFINE_GETIMPL_STORE( + DICompileUnit, + (SourceLanguage, IsOptimized, RuntimeVersion, EmissionKind, DWOId), Ops); +} + +DISubprogram *DILocalScope::getSubprogram() const { + if (auto *Block = dyn_cast<DILexicalBlockBase>(this)) + return Block->getScope()->getSubprogram(); + return const_cast<DISubprogram *>(cast<DISubprogram>(this)); +} + +DISubprogram *DISubprogram::getImpl( + LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + assert(isCanonical(LinkageName) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DISubprogram, + (Scope, getString(Name), getString(LinkageName), File, + Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, Flags, + IsOptimized, Function, TemplateParams, Declaration, + Variables)); + Metadata *Ops[] = {File, Scope, Name, Name, + LinkageName, Type, ContainingType, Function, + TemplateParams, Declaration, Variables}; + DEFINE_GETIMPL_STORE(DISubprogram, + (Line, ScopeLine, Virtuality, VirtualIndex, Flags, + IsLocalToUnit, IsDefinition, IsOptimized), + Ops); +} + +Function *DISubprogram::getFunction() const { + // FIXME: Should this be looking through bitcasts? + return dyn_cast_or_null<Function>(getFunctionConstant()); +} + +bool DISubprogram::describes(const Function *F) const { + assert(F && "Invalid function"); + if (F == getFunction()) + return true; + StringRef Name = getLinkageName(); + if (Name.empty()) + Name = getName(); + return F->getName() == Name; +} + +void DISubprogram::replaceFunction(Function *F) { + replaceFunction(F ? ConstantAsMetadata::get(F) + : static_cast<ConstantAsMetadata *>(nullptr)); +} + +DILexicalBlock *DILexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, + unsigned Column, StorageType Storage, + bool ShouldCreate) { + assert(Scope && "Expected scope"); + DEFINE_GETIMPL_LOOKUP(DILexicalBlock, (Scope, File, Line, Column)); + Metadata *Ops[] = {File, Scope}; + DEFINE_GETIMPL_STORE(DILexicalBlock, (Line, Column), Ops); +} + +DILexicalBlockFile *DILexicalBlockFile::getImpl(LLVMContext &Context, + Metadata *Scope, Metadata *File, + unsigned Discriminator, + StorageType Storage, + bool ShouldCreate) { + assert(Scope && "Expected scope"); + DEFINE_GETIMPL_LOOKUP(DILexicalBlockFile, (Scope, File, Discriminator)); + Metadata *Ops[] = {File, Scope}; + DEFINE_GETIMPL_STORE(DILexicalBlockFile, (Discriminator), Ops); +} + +DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DINamespace, (Scope, File, getString(Name), Line)); + Metadata *Ops[] = {File, Scope, Name}; + DEFINE_GETIMPL_STORE(DINamespace, (Line), Ops); +} + +DITemplateTypeParameter *DITemplateTypeParameter::getImpl(LLVMContext &Context, + MDString *Name, + Metadata *Type, + StorageType Storage, + bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (getString(Name), Type)); + Metadata *Ops[] = {Name, Type}; + DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DITemplateTypeParameter, Ops); +} + +DITemplateValueParameter *DITemplateValueParameter::getImpl( + LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter, + (Tag, getString(Name), Type, Value)); + Metadata *Ops[] = {Name, Type, Value}; + DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag), Ops); +} + +DIGlobalVariable * +DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, + Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + Metadata *Variable, + Metadata *StaticDataMemberDeclaration, + StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + assert(isCanonical(LinkageName) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DIGlobalVariable, + (Scope, getString(Name), getString(LinkageName), File, + Line, Type, IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration)); + Metadata *Ops[] = {Scope, Name, File, Type, + Name, LinkageName, Variable, StaticDataMemberDeclaration}; + DEFINE_GETIMPL_STORE(DIGlobalVariable, (Line, IsLocalToUnit, IsDefinition), + Ops); +} + +DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, + Metadata *Type, unsigned Arg, + unsigned Flags, StorageType Storage, + bool ShouldCreate) { + // 64K ought to be enough for any frontend. + assert(Arg <= UINT16_MAX && "Expected argument number to fit in 16-bits"); + + assert(Scope && "Expected scope"); + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DILocalVariable, (Tag, Scope, getString(Name), File, + Line, Type, Arg, Flags)); + Metadata *Ops[] = {Scope, Name, File, Type}; + DEFINE_GETIMPL_STORE(DILocalVariable, (Tag, Line, Arg, Flags), Ops); +} + +DIExpression *DIExpression::getImpl(LLVMContext &Context, + ArrayRef<uint64_t> Elements, + StorageType Storage, bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements)); + DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements)); +} + +unsigned DIExpression::ExprOperand::getSize() const { + switch (getOp()) { + case dwarf::DW_OP_bit_piece: + return 3; + case dwarf::DW_OP_plus: + return 2; + default: + return 1; + } +} + +bool DIExpression::isValid() const { + for (auto I = expr_op_begin(), E = expr_op_end(); I != E; ++I) { + // Check that there's space for the operand. + if (I->get() + I->getSize() > E->get()) + return false; + + // Check that the operand is valid. + switch (I->getOp()) { + default: + return false; + case dwarf::DW_OP_bit_piece: + // Piece expressions must be at the end. + return I->get() + I->getSize() == E->get(); + case dwarf::DW_OP_plus: + case dwarf::DW_OP_deref: + break; + } + } + return true; +} + +bool DIExpression::isBitPiece() const { + assert(isValid() && "Expected valid expression"); + if (unsigned N = getNumElements()) + if (N >= 3) + return getElement(N - 3) == dwarf::DW_OP_bit_piece; + return false; +} + +uint64_t DIExpression::getBitPieceOffset() const { + assert(isBitPiece() && "Expected bit piece"); + return getElement(getNumElements() - 2); +} + +uint64_t DIExpression::getBitPieceSize() const { + assert(isBitPiece() && "Expected bit piece"); + return getElement(getNumElements() - 1); +} + +DIObjCProperty *DIObjCProperty::getImpl( + LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, unsigned Attributes, + Metadata *Type, StorageType Storage, bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + assert(isCanonical(GetterName) && "Expected canonical MDString"); + assert(isCanonical(SetterName) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DIObjCProperty, + (getString(Name), File, Line, getString(GetterName), + getString(SetterName), Attributes, Type)); + Metadata *Ops[] = {Name, File, GetterName, SetterName, Type}; + DEFINE_GETIMPL_STORE(DIObjCProperty, (Line, Attributes), Ops); +} + +DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate) { + assert(isCanonical(Name) && "Expected canonical MDString"); + DEFINE_GETIMPL_LOOKUP(DIImportedEntity, + (Tag, Scope, Entity, Line, getString(Name))); + Metadata *Ops[] = {Scope, Entity, Name}; + DEFINE_GETIMPL_STORE(DIImportedEntity, (Tag, Line), Ops); +} diff --git a/contrib/llvm/lib/IR/DebugLoc.cpp b/contrib/llvm/lib/IR/DebugLoc.cpp index 075f295..72d5c0e 100644 --- a/contrib/llvm/lib/IR/DebugLoc.cpp +++ b/contrib/llvm/lib/IR/DebugLoc.cpp @@ -16,106 +16,87 @@ using namespace llvm; //===----------------------------------------------------------------------===// // DebugLoc Implementation //===----------------------------------------------------------------------===// +DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {} +DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {} -unsigned DebugLoc::getLine() const { return DILocation(Loc).getLineNumber(); } -unsigned DebugLoc::getCol() const { return DILocation(Loc).getColumnNumber(); } +DILocation *DebugLoc::get() const { + return cast_or_null<DILocation>(Loc.get()); +} + +unsigned DebugLoc::getLine() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getLine(); +} -MDNode *DebugLoc::getScope() const { return DILocation(Loc).getScope(); } +unsigned DebugLoc::getCol() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getColumn(); +} -MDNode *DebugLoc::getInlinedAt() const { - return DILocation(Loc).getOrigLocation(); +MDNode *DebugLoc::getScope() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getScope(); } -/// Return both the Scope and the InlinedAt values. -void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const { - Scope = getScope(); - IA = getInlinedAt(); +DILocation *DebugLoc::getInlinedAt() const { + assert(get() && "Expected valid DebugLoc"); + return get()->getInlinedAt(); } -MDNode *DebugLoc::getScopeNode() const { - if (MDNode *InlinedAt = getInlinedAt()) - return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(); - return getScope(); +MDNode *DebugLoc::getInlinedAtScope() const { + return cast<DILocation>(Loc)->getInlinedAtScope(); } DebugLoc DebugLoc::getFnDebugLoc() const { - const MDNode *Scope = getScopeNode(); - DISubprogram SP = getDISubprogram(Scope); - if (SP.isSubprogram()) - return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); + // FIXME: Add a method on \a DILocation that does this work. + const MDNode *Scope = getInlinedAtScope(); + if (auto *SP = getDISubprogram(Scope)) + return DebugLoc::get(SP->getScopeLine(), 0, SP); return DebugLoc(); } -DebugLoc DebugLoc::get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt) { +DebugLoc DebugLoc::get(unsigned Line, unsigned Col, const MDNode *Scope, + const MDNode *InlinedAt) { // If no scope is available, this is an unknown location. if (!Scope) return DebugLoc(); - // Saturate line and col to "unknown". - // FIXME: Allow 16-bits for columns. - if (Col > 255) Col = 0; - if (Line >= (1 << 24)) Line = 0; - - return getFromDILocation( - MDLocation::get(Scope->getContext(), Line, Col, Scope, InlinedAt)); -} - -/// getAsMDNode - This method converts the compressed DebugLoc node into a -/// DILocation-compatible MDNode. -MDNode *DebugLoc::getAsMDNode() const { return Loc; } - -/// getFromDILocation - Translate the DILocation quad into a DebugLoc. -DebugLoc DebugLoc::getFromDILocation(MDNode *N) { - DebugLoc Loc; - Loc.Loc.reset(N); - return Loc; -} - -/// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. -DebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) { - DILexicalBlock LexBlock(N); - MDNode *Scope = LexBlock.getContext(); - if (!Scope) return DebugLoc(); - return get(LexBlock.getLineNumber(), LexBlock.getColumnNumber(), Scope, - nullptr); + return DILocation::get(Scope->getContext(), Line, Col, + const_cast<MDNode *>(Scope), + const_cast<MDNode *>(InlinedAt)); } void DebugLoc::dump() const { #ifndef NDEBUG - if (!isUnknown()) { - dbgs() << getLine(); - if (getCol() != 0) - dbgs() << ',' << getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt()); - if (!InlinedAtDL.isUnknown()) { - dbgs() << " @ "; - InlinedAtDL.dump(); - } else - dbgs() << "\n"; - } + if (!Loc) + return; + + dbgs() << getLine(); + if (getCol() != 0) + dbgs() << ',' << getCol(); + if (DebugLoc InlinedAtDL = DebugLoc(getInlinedAt())) { + dbgs() << " @ "; + InlinedAtDL.dump(); + } else + dbgs() << "\n"; #endif } void DebugLoc::print(raw_ostream &OS) const { - if (!isUnknown()) { - // Print source line info. - DIScope Scope(getScope()); - assert((!Scope || Scope.isScope()) && - "Scope of a DebugLoc should be null or a DIScope."); - if (Scope) - OS << Scope.getFilename(); - else - OS << "<unknown>"; - OS << ':' << getLine(); - if (getCol() != 0) - OS << ':' << getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt()); - if (!InlinedAtDL.isUnknown()) { - OS << " @[ "; - InlinedAtDL.print(OS); - OS << " ]"; - } + if (!Loc) + return; + + // Print source line info. + auto *Scope = cast<DIScope>(getScope()); + OS << Scope->getFilename(); + OS << ':' << getLine(); + if (getCol() != 0) + OS << ':' << getCol(); + + if (DebugLoc InlinedAtDL = getInlinedAt()) { + OS << " @[ "; + InlinedAtDL.print(OS); + OS << " ]"; } } diff --git a/contrib/llvm/lib/IR/DiagnosticInfo.cpp b/contrib/llvm/lib/IR/DiagnosticInfo.cpp index cfb699a..5de9289 100644 --- a/contrib/llvm/lib/IR/DiagnosticInfo.cpp +++ b/contrib/llvm/lib/IR/DiagnosticInfo.cpp @@ -22,9 +22,9 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" -#include "llvm/Support/Atomic.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Regex.h" +#include <atomic> #include <string> using namespace llvm; @@ -84,11 +84,11 @@ PassRemarksAnalysis( "the given regular expression"), cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, cl::ZeroOrMore); -} +} // namespace int llvm::getNextAvailablePluginDiagnosticKind() { - static sys::cas_flag PluginKindID = DK_FirstPluginKind; - return (int)sys::AtomicIncrement(&PluginKindID); + static std::atomic<int> PluginKindID(DK_FirstPluginKind); + return ++PluginKindID; } DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, @@ -129,16 +129,17 @@ void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { } bool DiagnosticInfoOptimizationBase::isLocationAvailable() const { - return getDebugLoc().isUnknown() == false; + return getDebugLoc(); } 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(); + DILocation *L = getDebugLoc(); + assert(L != nullptr && "debug location is invalid"); + *Filename = L->getFilename(); + *Line = L->getLine(); + *Column = L->getColumn(); } const std::string DiagnosticInfoOptimizationBase::getLocationStr() const { @@ -147,7 +148,7 @@ const std::string DiagnosticInfoOptimizationBase::getLocationStr() const { unsigned Column = 0; if (isLocationAvailable()) getLocation(&Filename, &Line, &Column); - return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); + return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); } void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { @@ -169,6 +170,10 @@ bool DiagnosticInfoOptimizationRemarkAnalysis::isEnabled() const { PassRemarksAnalysisOptLoc.Pattern->match(getPassName()); } +void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { + DP << Diagnostic; +} + void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, const Function &Fn, const DebugLoc &DLoc, const Twine &Msg) { diff --git a/contrib/llvm/lib/IR/DiagnosticPrinter.cpp b/contrib/llvm/lib/IR/DiagnosticPrinter.cpp index f25fc20..659ff49 100644 --- a/contrib/llvm/lib/IR/DiagnosticPrinter.cpp +++ b/contrib/llvm/lib/IR/DiagnosticPrinter.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" using namespace llvm; @@ -105,3 +106,12 @@ DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Module &M) { Stream << M.getModuleIdentifier(); return *this; } + +// Other types. +DiagnosticPrinter &DiagnosticPrinterRawOStream:: +operator<<(const SMDiagnostic &Diag) { + // We don't have to print the SMDiagnostic kind, as the diagnostic severity + // is printed by the diagnostic handler. + Diag.print("", Stream, /*ShowColors=*/true, /*ShowKindLabel=*/false); + return *this; +} diff --git a/contrib/llvm/lib/IR/Dominators.cpp b/contrib/llvm/lib/IR/Dominators.cpp index 9b6ff1e..e325889 100644 --- a/contrib/llvm/lib/IR/Dominators.cpp +++ b/contrib/llvm/lib/IR/Dominators.cpp @@ -282,9 +282,6 @@ bool DominatorTree::isReachableFromEntry(const Use &U) const { } void DominatorTree::verifyDomTree() const { - if (!VerifyDomInfo) - return; - Function &F = *getRoot()->getParent(); DominatorTree OtherDT; @@ -350,7 +347,10 @@ bool DominatorTreeWrapperPass::runOnFunction(Function &F) { return false; } -void DominatorTreeWrapperPass::verifyAnalysis() const { DT.verifyDomTree(); } +void DominatorTreeWrapperPass::verifyAnalysis() const { + if (VerifyDomInfo) + DT.verifyDomTree(); +} void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const { DT.print(OS); diff --git a/contrib/llvm/lib/IR/Function.cpp b/contrib/llvm/lib/IR/Function.cpp index bfd0ca6..b50ad12 100644 --- a/contrib/llvm/lib/IR/Function.cpp +++ b/contrib/llvm/lib/IR/Function.cpp @@ -19,10 +19,13 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/RWMutex.h" @@ -117,6 +120,12 @@ uint64_t Argument::getDereferenceableBytes() const { return getParent()->getDereferenceableBytes(getArgNo()+1); } +uint64_t Argument::getDereferenceableOrNullBytes() const { + assert(getType()->isPointerTy() && + "Only pointers have dereferenceable bytes"); + return getParent()->getDereferenceableOrNullBytes(getArgNo()+1); +} + /// hasNestAttr - Return true if this argument has the nest attribute on /// it in its containing function. bool Argument::hasNestAttr() const { @@ -145,10 +154,8 @@ bool Argument::hasNoCaptureAttr() const { /// it in its containing function. bool Argument::hasStructRetAttr() const { if (!getType()->isPointerTy()) return false; - if (this != getParent()->arg_begin()) - return false; // StructRet param must be first param return getParent()->getAttributes(). - hasAttribute(1, Attribute::StructRet); + hasAttribute(getArgNo()+1, Attribute::StructRet); } /// hasReturnedAttr - Return true if this argument has the returned attribute on @@ -206,18 +213,18 @@ void Argument::removeAttr(AttributeSet AS) { //===----------------------------------------------------------------------===// bool Function::isMaterializable() const { - return getGlobalObjectSubClassData(); + return getGlobalObjectSubClassData() & IsMaterializableBit; } -void Function::setIsMaterializable(bool V) { setGlobalObjectSubClassData(V); } +void Function::setIsMaterializable(bool V) { + setGlobalObjectBit(IsMaterializableBit, V); +} LLVMContext &Function::getContext() const { return getType()->getContext(); } -FunctionType *Function::getFunctionType() const { - return cast<FunctionType>(getType()->getElementType()); -} +FunctionType *Function::getFunctionType() const { return Ty; } bool Function::isVarArg() const { return getFunctionType()->isVarArg(); @@ -241,11 +248,12 @@ void Function::eraseFromParent() { Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name, Module *ParentModule) - : GlobalObject(PointerType::getUnqual(Ty), Value::FunctionVal, nullptr, 0, - Linkage, name) { + : GlobalObject(PointerType::getUnqual(Ty), Value::FunctionVal, + OperandTraits<Function>::op_begin(this), 0, Linkage, name), + Ty(Ty) { assert(FunctionType::isValidReturnType(getReturnType()) && "invalid return type"); - setIsMaterializable(false); + setGlobalObjectSubClassData(0); SymTab = new ValueSymbolTable(); // If the function has arguments, mark them as lazily built. @@ -256,9 +264,10 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name, ParentModule->getFunctionList().push_back(this); // Ensure intrinsics have the right parameter attributes. - if (unsigned IID = getIntrinsicID()) - setAttributes(Intrinsic::getAttributes(getContext(), Intrinsic::ID(IID))); - + // Note, the IntID field will have been set in Value::setName if this function + // name is a valid intrinsic ID. + if (IntID) + setAttributes(Intrinsic::getAttributes(getContext(), IntID)); } Function::~Function() { @@ -271,9 +280,8 @@ Function::~Function() { // Remove the function from the on-the-side GC table. clearGC(); - // Remove the intrinsicID from the Cache. - if (getValueName() && isIntrinsic()) - getContext().pImpl->IntrinsicIDCache.erase(this); + // FIXME: needed by operator delete + setFunctionNumOperands(1); } void Function::BuildLazyArguments() const { @@ -323,6 +331,11 @@ void Function::dropAllReferences() { // Prefix and prologue data are stored in a side table. setPrefixData(nullptr); setPrologueData(nullptr); + + // Metadata is stored in a side-table. + clearMetadata(); + + setPersonalityFn(nullptr); } void Function::addAttribute(unsigned i, Attribute::AttrKind attr) { @@ -343,6 +356,18 @@ void Function::removeAttributes(unsigned i, AttributeSet attrs) { setAttributes(PAL); } +void Function::addDereferenceableAttr(unsigned i, uint64_t Bytes) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); + setAttributes(PAL); +} + +void Function::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); + setAttributes(PAL); +} + // Maintain the GC name for each function in an on-the-side table. This saves // allocating an additional word in Function for programs which do not use GC // (i.e., most programs) at the cost of increased overhead for clients which do @@ -406,35 +431,15 @@ void Function::copyAttributesFrom(const GlobalValue *Src) { setPrologueData(SrcF->getPrologueData()); else setPrologueData(nullptr); + if (SrcF->hasPersonalityFn()) + setPersonalityFn(SrcF->getPersonalityFn()); + else + setPersonalityFn(nullptr); } -/// getIntrinsicID - This method returns the ID number of the specified -/// function, or Intrinsic::not_intrinsic if the function is not an -/// intrinsic, or if the pointer is null. This value is always defined to be -/// zero to allow easy checking for whether a function is intrinsic or not. The -/// particular intrinsic functions which correspond to this value are defined in -/// llvm/Intrinsics.h. Results are cached in the LLVM context, subsequent -/// requests for the same ID return results much faster from the cache. -/// -unsigned Function::getIntrinsicID() const { - const ValueName *ValName = this->getValueName(); - if (!ValName || !isIntrinsic()) - return 0; - - LLVMContextImpl::IntrinsicIDCacheTy &IntrinsicIDCache = - getContext().pImpl->IntrinsicIDCache; - if (!IntrinsicIDCache.count(this)) { - unsigned Id = lookupIntrinsicID(); - IntrinsicIDCache[this]=Id; - return Id; - } - return IntrinsicIDCache[this]; -} - -/// This private method does the actual lookup of an intrinsic ID when the query -/// could not be answered from the cache. -unsigned Function::lookupIntrinsicID() const { - const ValueName *ValName = this->getValueName(); +/// \brief This does the actual lookup of an intrinsic ID which +/// matches the given function name. +static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) { unsigned Len = ValName->getKeyLength(); const char *Name = ValName->getKeyData(); @@ -442,7 +447,16 @@ unsigned Function::lookupIntrinsicID() const { #include "llvm/IR/Intrinsics.gen" #undef GET_FUNCTION_RECOGNIZER - return 0; + return Intrinsic::not_intrinsic; +} + +void Function::recalculateIntrinsicID() { + const ValueName *ValName = this->getValueName(); + if (!ValName || !isIntrinsic()) { + IntID = Intrinsic::not_intrinsic; + return; + } + IntID = lookupIntrinsicID(ValName); } /// Returns a stable mangling for the type specified for use in the name @@ -455,6 +469,10 @@ unsigned Function::lookupIntrinsicID() const { /// which can't be confused with it's prefix. This ensures we don't have /// collisions between two unrelated function types. Otherwise, you might /// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.) +/// Manglings of integers, floats, and vectors ('i', 'f', and 'v' prefix in most +/// cases) fall back to the MVT codepath, where they could be mangled to +/// 'x86mmx', for example; matching on derived types is not sufficient to mangle +/// everything. static std::string getMangledTypeStr(Type* Ty) { std::string Result; if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) { @@ -464,10 +482,8 @@ static std::string getMangledTypeStr(Type* 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"); + assert(!STyp->isLiteral() && "TODO: implement literal types"); + Result += STyp->getName(); } else if (FunctionType* FT = dyn_cast<FunctionType>(Ty)) { Result += "f_" + getMangledTypeStr(FT->getReturnType()); for (size_t i = 0; i < FT->getNumParams(); i++) @@ -538,7 +554,9 @@ enum IIT_Info { IIT_VARARG = 28, IIT_HALF_VEC_ARG = 29, IIT_SAME_VEC_WIDTH_ARG = 30, - IIT_PTR_TO_ARG = 31 + IIT_PTR_TO_ARG = 31, + IIT_VEC_OF_PTRS_TO_ELT = 32, + IIT_I128 = 33 }; @@ -585,6 +603,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, case IIT_I64: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64)); return; + case IIT_I128: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 128)); + return; case IIT_V1: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 1)); DecodeIITType(NextElt, Infos, OutputTable); @@ -658,6 +679,12 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, ArgInfo)); return; } + case IIT_VEC_OF_PTRS_TO_ELT: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::VecOfPtrsToElt, + ArgInfo)); + return; + } case IIT_EMPTYSTRUCT: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0)); return; @@ -777,6 +804,15 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos, Type *Ty = Tys[D.getArgumentNumber()]; return PointerType::getUnqual(Ty); } + case IITDescriptor::VecOfPtrsToElt: { + Type *Ty = Tys[D.getArgumentNumber()]; + VectorType *VTy = dyn_cast<VectorType>(Ty); + if (!VTy) + llvm_unreachable("Expected an argument of Vector Type"); + Type *EltTy = VTy->getVectorElementType(); + return VectorType::get(PointerType::getUnqual(EltTy), + VTy->getNumElements()); + } } llvm_unreachable("unhandled"); } @@ -810,6 +846,18 @@ bool Intrinsic::isOverloaded(ID id) { #undef GET_INTRINSIC_OVERLOAD_TABLE } +bool Intrinsic::isLeaf(ID id) { + switch (id) { + default: + return true; + + case Intrinsic::experimental_gc_statepoint: + case Intrinsic::experimental_patchpoint_void: + case Intrinsic::experimental_patchpoint_i64: + return false; + } +} + /// This defines the "Intrinsic::getAttributes(ID id)" method. #define GET_INTRINSIC_ATTRIBUTES #include "llvm/IR/Intrinsics.gen" @@ -933,3 +981,38 @@ void Function::setPrologueData(Constant *PrologueData) { } setValueSubclassData(PDData); } + +void Function::setEntryCount(uint64_t Count) { + MDBuilder MDB(getContext()); + setMetadata(LLVMContext::MD_prof, MDB.createFunctionEntryCount(Count)); +} + +Optional<uint64_t> Function::getEntryCount() const { + MDNode *MD = getMetadata(LLVMContext::MD_prof); + if (MD && MD->getOperand(0)) + if (MDString *MDS = dyn_cast<MDString>(MD->getOperand(0))) + if (MDS->getString().equals("function_entry_count")) { + ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(1)); + return CI->getValue().getZExtValue(); + } + return None; +} + +void Function::setPersonalityFn(Constant *C) { + if (!C) { + if (hasPersonalityFn()) { + // Note, the num operands is used to compute the offset of the operand, so + // the order here matters. Clearing the operand then clearing the num + // operands ensures we have the correct offset to the operand. + Op<0>().set(nullptr); + setFunctionNumOperands(0); + } + } else { + // Note, the num operands is used to compute the offset of the operand, so + // the order here matters. We need to set num operands to 1 first so that + // we get the correct offset to the first operand when we set it. + if (!hasPersonalityFn()) + setFunctionNumOperands(1); + Op<0>().set(C); + } +} diff --git a/contrib/llvm/lib/IR/GCOV.cpp b/contrib/llvm/lib/IR/GCOV.cpp index 88e0cd0..a0a3db4 100644 --- a/contrib/llvm/lib/IR/GCOV.cpp +++ b/contrib/llvm/lib/IR/GCOV.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <system_error> using namespace llvm; @@ -28,12 +29,16 @@ using namespace llvm; /// readGCNO - Read GCNO buffer. bool GCOVFile::readGCNO(GCOVBuffer &Buffer) { - if (!Buffer.readGCNOFormat()) return false; - if (!Buffer.readGCOVVersion(Version)) return false; + if (!Buffer.readGCNOFormat()) + return false; + if (!Buffer.readGCOVVersion(Version)) + return false; - if (!Buffer.readInt(Checksum)) return false; + if (!Buffer.readInt(Checksum)) + return false; while (true) { - if (!Buffer.readFunctionTag()) break; + if (!Buffer.readFunctionTag()) + break; auto GFun = make_unique<GCOVFunction>(*this); if (!GFun->readGCNO(Buffer, Version)) return false; @@ -48,19 +53,22 @@ bool GCOVFile::readGCNO(GCOVBuffer &Buffer) { /// called after readGCNO(). bool GCOVFile::readGCDA(GCOVBuffer &Buffer) { assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()"); - if (!Buffer.readGCDAFormat()) return false; + if (!Buffer.readGCDAFormat()) + return false; GCOV::GCOVVersion GCDAVersion; - if (!Buffer.readGCOVVersion(GCDAVersion)) return false; + if (!Buffer.readGCOVVersion(GCDAVersion)) + return false; if (Version != GCDAVersion) { errs() << "GCOV versions do not match.\n"; return false; } uint32_t GCDAChecksum; - if (!Buffer.readInt(GCDAChecksum)) return false; + if (!Buffer.readInt(GCDAChecksum)) + return false; if (Checksum != GCDAChecksum) { - errs() << "File checksums do not match: " << Checksum << " != " - << GCDAChecksum << ".\n"; + errs() << "File checksums do not match: " << Checksum + << " != " << GCDAChecksum << ".\n"; return false; } for (size_t i = 0, e = Functions.size(); i < e; ++i) { @@ -74,15 +82,20 @@ bool GCOVFile::readGCDA(GCOVBuffer &Buffer) { if (Buffer.readObjectTag()) { uint32_t Length; uint32_t Dummy; - if (!Buffer.readInt(Length)) return false; - if (!Buffer.readInt(Dummy)) return false; // checksum - if (!Buffer.readInt(Dummy)) return false; // num - if (!Buffer.readInt(RunCount)) return false; - Buffer.advanceCursor(Length-3); + if (!Buffer.readInt(Length)) + return false; + if (!Buffer.readInt(Dummy)) + return false; // checksum + if (!Buffer.readInt(Dummy)) + return false; // num + if (!Buffer.readInt(RunCount)) + return false; + Buffer.advanceCursor(Length - 3); } while (Buffer.readProgramTag()) { uint32_t Length; - if (!Buffer.readInt(Length)) return false; + if (!Buffer.readInt(Length)) + return false; Buffer.advanceCursor(Length); ++ProgramCount; } @@ -112,21 +125,28 @@ void GCOVFile::collectLineCounts(FileInfo &FI) { /// occurs. bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { uint32_t Dummy; - if (!Buff.readInt(Dummy)) return false; // Function header length - if (!Buff.readInt(Ident)) return false; - if (!Buff.readInt(Checksum)) return false; + if (!Buff.readInt(Dummy)) + return false; // Function header length + if (!Buff.readInt(Ident)) + return false; + if (!Buff.readInt(Checksum)) + return false; if (Version != GCOV::V402) { uint32_t CfgChecksum; - if (!Buff.readInt(CfgChecksum)) return false; + if (!Buff.readInt(CfgChecksum)) + return false; if (Parent.getChecksum() != CfgChecksum) { errs() << "File checksums do not match: " << Parent.getChecksum() << " != " << CfgChecksum << " in (" << Name << ").\n"; return false; } } - if (!Buff.readString(Name)) return false; - if (!Buff.readString(Filename)) return false; - if (!Buff.readInt(LineNumber)) return false; + if (!Buff.readString(Name)) + return false; + if (!Buff.readString(Filename)) + return false; + if (!Buff.readInt(LineNumber)) + return false; // read blocks. if (!Buff.readBlockTag()) { @@ -134,19 +154,23 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { return false; } uint32_t BlockCount; - if (!Buff.readInt(BlockCount)) return false; + if (!Buff.readInt(BlockCount)) + return false; for (uint32_t i = 0, e = BlockCount; i != e; ++i) { - if (!Buff.readInt(Dummy)) return false; // Block flags; + if (!Buff.readInt(Dummy)) + return false; // Block flags; Blocks.push_back(make_unique<GCOVBlock>(*this, i)); } // read edges. while (Buff.readEdgeTag()) { uint32_t EdgeCount; - if (!Buff.readInt(EdgeCount)) return false; + if (!Buff.readInt(EdgeCount)) + return false; EdgeCount = (EdgeCount - 1) / 2; uint32_t BlockNo; - if (!Buff.readInt(BlockNo)) return false; + if (!Buff.readInt(BlockNo)) + return false; if (BlockNo >= BlockCount) { errs() << "Unexpected block number: " << BlockNo << " (in " << Name << ").\n"; @@ -154,12 +178,14 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { } for (uint32_t i = 0, e = EdgeCount; i != e; ++i) { uint32_t Dst; - if (!Buff.readInt(Dst)) return false; + if (!Buff.readInt(Dst)) + return false; Edges.push_back(make_unique<GCOVEdge>(*Blocks[BlockNo], *Blocks[Dst])); GCOVEdge *Edge = Edges.back().get(); Blocks[BlockNo]->addDstEdge(Edge); Blocks[Dst]->addSrcEdge(Edge); - if (!Buff.readInt(Dummy)) return false; // Edge flag + if (!Buff.readInt(Dummy)) + return false; // Edge flag } } @@ -167,11 +193,13 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { while (Buff.readLineTag()) { uint32_t LineTableLength; // Read the length of this line table. - if (!Buff.readInt(LineTableLength)) return false; - uint32_t EndPos = Buff.getCursor() + LineTableLength*4; + if (!Buff.readInt(LineTableLength)) + return false; + uint32_t EndPos = Buff.getCursor() + LineTableLength * 4; uint32_t BlockNo; // Read the block number this table is associated with. - if (!Buff.readInt(BlockNo)) return false; + if (!Buff.readInt(BlockNo)) + return false; if (BlockNo >= BlockCount) { errs() << "Unexpected block number: " << BlockNo << " (in " << Name << ").\n"; @@ -180,13 +208,15 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { GCOVBlock &Block = *Blocks[BlockNo]; // Read the word that pads the beginning of the line table. This may be a // flag of some sort, but seems to always be zero. - if (!Buff.readInt(Dummy)) return false; + if (!Buff.readInt(Dummy)) + return false; // Line information starts here and continues up until the last word. if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) { StringRef F; // Read the source file name. - if (!Buff.readString(F)) return false; + if (!Buff.readString(F)) + return false; if (Filename != F) { errs() << "Multiple sources for a single basic block: " << Filename << " != " << F << " (in " << Name << ").\n"; @@ -195,17 +225,21 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { // Read lines up to, but not including, the null terminator. while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) { uint32_t Line; - if (!Buff.readInt(Line)) return false; + if (!Buff.readInt(Line)) + return false; // Line 0 means this instruction was injected by the compiler. Skip it. - if (!Line) continue; + if (!Line) + continue; Block.addLine(Line); } // Read the null terminator. - if (!Buff.readInt(Dummy)) return false; + if (!Buff.readInt(Dummy)) + return false; } // The last word is either a flag or padding, it isn't clear which. Skip // over it. - if (!Buff.readInt(Dummy)) return false; + if (!Buff.readInt(Dummy)) + return false; } return true; } @@ -214,27 +248,31 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { /// occurs. bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { uint32_t Dummy; - if (!Buff.readInt(Dummy)) return false; // Function header length + if (!Buff.readInt(Dummy)) + return false; // Function header length uint32_t GCDAIdent; - if (!Buff.readInt(GCDAIdent)) return false; + if (!Buff.readInt(GCDAIdent)) + return false; if (Ident != GCDAIdent) { - errs() << "Function identifiers do not match: " << Ident << " != " - << GCDAIdent << " (in " << Name << ").\n"; + errs() << "Function identifiers do not match: " << Ident + << " != " << GCDAIdent << " (in " << Name << ").\n"; return false; } uint32_t GCDAChecksum; - if (!Buff.readInt(GCDAChecksum)) return false; + if (!Buff.readInt(GCDAChecksum)) + return false; if (Checksum != GCDAChecksum) { - errs() << "Function checksums do not match: " << Checksum << " != " - << GCDAChecksum << " (in " << Name << ").\n"; + errs() << "Function checksums do not match: " << Checksum + << " != " << GCDAChecksum << " (in " << Name << ").\n"; return false; } uint32_t CfgChecksum; if (Version != GCOV::V402) { - if (!Buff.readInt(CfgChecksum)) return false; + if (!Buff.readInt(CfgChecksum)) + return false; if (Parent.getChecksum() != CfgChecksum) { errs() << "File checksums do not match: " << Parent.getChecksum() << " != " << CfgChecksum << " (in " << Name << ").\n"; @@ -243,7 +281,8 @@ bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { } StringRef GCDAName; - if (!Buff.readString(GCDAName)) return false; + if (!Buff.readString(GCDAName)) + return false; if (Name != GCDAName) { errs() << "Function names do not match: " << Name << " != " << GCDAName << ".\n"; @@ -256,7 +295,8 @@ bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { } uint32_t Count; - if (!Buff.readInt(Count)) return false; + if (!Buff.readInt(Count)) + return false; Count /= 2; // This for loop adds the counts for each block. A second nested loop is @@ -271,13 +311,14 @@ bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { errs() << "(" << Name << ") has arcs from exit block.\n"; GCOVBlock &Block = *Blocks[BlockNo]; for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End; - ++EdgeNo) { + ++EdgeNo) { if (Count == 0) { errs() << "Unexpected number of edges (in " << Name << ").\n"; return false; } uint64_t ArcCount; - if (!Buff.readInt64(ArcCount)) return false; + if (!Buff.readInt64(ArcCount)) + return false; Block.addCount(EdgeNo, ArcCount); --Count; } @@ -351,9 +392,8 @@ void GCOVBlock::sortDstEdges() { /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVBlock::collectLineCounts(FileInfo &FI) { - for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) - FI.addBlockLine(Parent.getFilename(), *I, this); + for (uint32_t N : Lines) + FI.addBlockLine(Parent.getFilename(), N, this); } /// dump - Dump GCOVBlock content to dbgs() for debugging purposes. @@ -361,25 +401,20 @@ void GCOVBlock::dump() const { dbgs() << "Block : " << Number << " Counter : " << Counter << "\n"; if (!SrcEdges.empty()) { dbgs() << "\tSource Edges : "; - for (EdgeIterator I = SrcEdges.begin(), E = SrcEdges.end(); I != E; ++I) { - const GCOVEdge *Edge = *I; + for (const GCOVEdge *Edge : SrcEdges) dbgs() << Edge->Src.Number << " (" << Edge->Count << "), "; - } dbgs() << "\n"; } if (!DstEdges.empty()) { dbgs() << "\tDestination Edges : "; - for (EdgeIterator I = DstEdges.begin(), E = DstEdges.end(); I != E; ++I) { - const GCOVEdge *Edge = *I; + for (const GCOVEdge *Edge : DstEdges) dbgs() << Edge->Dst.Number << " (" << Edge->Count << "), "; - } dbgs() << "\n"; } if (!Lines.empty()) { dbgs() << "\tLines : "; - for (SmallVectorImpl<uint32_t>::const_iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) - dbgs() << (*I) << ","; + for (uint32_t N : Lines) + dbgs() << (N) << ","; dbgs() << "\n"; } } @@ -391,7 +426,7 @@ void GCOVBlock::dump() const { static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) { if (!Numerator) return 0; - return Numerator/Divisor; + return Numerator / Divisor; } // This custom division function mimics gcov's branch ouputs: @@ -403,7 +438,7 @@ static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) { if (Numerator == Divisor) return 100; - uint8_t Res = (Numerator*100+Divisor/2) / Divisor; + uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor; if (Res == 0) return 1; if (Res == 100) @@ -411,10 +446,10 @@ static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) { return Res; } +namespace { struct formatBranchInfo { - formatBranchInfo(const GCOVOptions &Options, uint64_t Count, - uint64_t Total) : - Options(Options), Count(Count), Total(Total) {} + formatBranchInfo(const GCOVOptions &Options, uint64_t Count, uint64_t Total) + : Options(Options), Count(Count), Total(Total) {} void print(raw_ostream &OS) const { if (!Total) @@ -435,10 +470,10 @@ static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) { return OS; } -namespace { class LineConsumer { std::unique_ptr<MemoryBuffer> Buffer; StringRef Remaining; + public: LineConsumer(StringRef Filename) { ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = @@ -461,7 +496,7 @@ public: OS << format("%5u:", LineNum) << Line << "\n"; } }; -} +} // namespace /// Convert a path to a gcov filename. If PreservePaths is true, this /// translates "/" to "#", ".." to "^", and drops ".", to match gcov. @@ -510,8 +545,7 @@ std::string FileInfo::getCoveragePath(StringRef Filename, if (Options.LongFileNames && !Filename.equals(MainFilename)) CoveragePath = mangleCoveragePath(MainFilename, Options.PreservePaths) + "##"; - CoveragePath += - mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov"; + CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov"; return CoveragePath; } @@ -521,7 +555,7 @@ FileInfo::openCoveragePath(StringRef CoveragePath) { return llvm::make_unique<raw_null_ostream>(); std::error_code EC; - auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath.str(), EC, + auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath, EC, sys::fs::F_Text); if (EC) { errs() << EC.message() << "\n"; @@ -531,47 +565,44 @@ FileInfo::openCoveragePath(StringRef CoveragePath) { } /// print - Print source files with collected line count information. -void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, - StringRef GCDAFile) { - for (StringMap<LineData>::const_iterator I = LineInfo.begin(), - E = LineInfo.end(); I != E; ++I) { - StringRef Filename = I->first(); +void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename, + StringRef GCNOFile, StringRef GCDAFile) { + for (const auto &LI : LineInfo) { + StringRef Filename = LI.first(); auto AllLines = LineConsumer(Filename); std::string CoveragePath = getCoveragePath(Filename, MainFilename); - std::unique_ptr<raw_ostream> S = openCoveragePath(CoveragePath); - raw_ostream &OS = *S; + std::unique_ptr<raw_ostream> CovStream = openCoveragePath(CoveragePath); + raw_ostream &CovOS = *CovStream; - OS << " -: 0:Source:" << Filename << "\n"; - OS << " -: 0:Graph:" << GCNOFile << "\n"; - OS << " -: 0:Data:" << GCDAFile << "\n"; - OS << " -: 0:Runs:" << RunCount << "\n"; - OS << " -: 0:Programs:" << ProgramCount << "\n"; + CovOS << " -: 0:Source:" << Filename << "\n"; + CovOS << " -: 0:Graph:" << GCNOFile << "\n"; + CovOS << " -: 0:Data:" << GCDAFile << "\n"; + CovOS << " -: 0:Runs:" << RunCount << "\n"; + CovOS << " -: 0:Programs:" << ProgramCount << "\n"; - const LineData &Line = I->second; + const LineData &Line = LI.second; GCOVCoverage FileCoverage(Filename); - for (uint32_t LineIndex = 0; - LineIndex < Line.LastLine || !AllLines.empty(); ++LineIndex) { + for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty(); + ++LineIndex) { if (Options.BranchInfo) { FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex); if (FuncsIt != Line.Functions.end()) - printFunctionSummary(OS, FuncsIt->second); + printFunctionSummary(CovOS, FuncsIt->second); } BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex); if (BlocksIt == Line.Blocks.end()) { // No basic blocks are on this line. Not an executable line of code. - OS << " -:"; - AllLines.printNext(OS, LineIndex + 1); + CovOS << " -:"; + AllLines.printNext(CovOS, LineIndex + 1); } else { const BlockVector &Blocks = BlocksIt->second; // Add up the block counts to form line counts. DenseMap<const GCOVFunction *, bool> LineExecs; uint64_t LineCount = 0; - for (BlockVector::const_iterator I = Blocks.begin(), E = Blocks.end(); - I != E; ++I) { - const GCOVBlock *Block = *I; + for (const GCOVBlock *Block : Blocks) { if (Options.AllBlocks) { // Only take the highest block count for that line. uint64_t BlockCount = Block->getCount(); @@ -595,8 +626,8 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, // one of the blocks are executed. const GCOVFunction *Function = &Block->getParent(); if (FuncCoverages.find(Function) == FuncCoverages.end()) { - std::pair<const GCOVFunction *, GCOVCoverage> - KeyValue(Function, GCOVCoverage(Function->getName())); + std::pair<const GCOVFunction *, GCOVCoverage> KeyValue( + Function, GCOVCoverage(Function->getName())); FuncCoverages.insert(KeyValue); } GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second; @@ -617,32 +648,30 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, } if (LineCount == 0) - OS << " #####:"; + CovOS << " #####:"; else { - OS << format("%9" PRIu64 ":", LineCount); + CovOS << format("%9" PRIu64 ":", LineCount); ++FileCoverage.LinesExec; } ++FileCoverage.LogicalLines; - AllLines.printNext(OS, LineIndex + 1); + AllLines.printNext(CovOS, LineIndex + 1); uint32_t BlockNo = 0; uint32_t EdgeNo = 0; - for (BlockVector::const_iterator I = Blocks.begin(), E = Blocks.end(); - I != E; ++I) { - const GCOVBlock *Block = *I; - + for (const GCOVBlock *Block : Blocks) { // Only print block and branch information at the end of the block. - if (Block->getLastLine() != LineIndex+1) + if (Block->getLastLine() != LineIndex + 1) continue; if (Options.AllBlocks) - printBlockInfo(OS, *Block, LineIndex, BlockNo); + printBlockInfo(CovOS, *Block, LineIndex, BlockNo); if (Options.BranchInfo) { size_t NumEdges = Block->getNumDstEdges(); if (NumEdges > 1) - printBranchInfo(OS, *Block, FileCoverage, EdgeNo); + printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo); else if (Options.UncondBranch && NumEdges == 1) - printUncondBranchInfo(OS, EdgeNo, (*Block->dst_begin())->Count); + printUncondBranchInfo(CovOS, EdgeNo, + (*Block->dst_begin())->Count); } } } @@ -652,30 +681,25 @@ void FileInfo::print(StringRef MainFilename, StringRef GCNOFile, // FIXME: There is no way to detect calls given current instrumentation. if (Options.FuncCoverage) - printFuncCoverage(); - printFileCoverage(); + printFuncCoverage(InfoOS); + printFileCoverage(InfoOS); return; } /// printFunctionSummary - Print function and block summary. void FileInfo::printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const { - for (FunctionVector::const_iterator I = Funcs.begin(), E = Funcs.end(); - I != E; ++I) { - const GCOVFunction *Func = *I; + for (const GCOVFunction *Func : Funcs) { uint64_t EntryCount = Func->getEntryCount(); uint32_t BlocksExec = 0; - for (GCOVFunction::BlockIterator I = Func->block_begin(), - E = Func->block_end(); I != E; ++I) { - const GCOVBlock &Block = **I; + for (const GCOVBlock &Block : Func->blocks()) if (Block.getNumDstEdges() && Block.getCount()) - ++BlocksExec; - } + ++BlocksExec; OS << "function " << Func->getName() << " called " << EntryCount - << " returned " << safeDiv(Func->getExitCount()*100, EntryCount) + << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount) << "% blocks executed " - << safeDiv(BlocksExec*100, Func->getNumBlocks()-1) << "%\n"; + << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n"; } } @@ -686,7 +710,7 @@ void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, OS << " $$$$$:"; else OS << format("%9" PRIu64 ":", Block.getCount()); - OS << format("%5u-block %2u\n", LineIndex+1, BlockNo++); + OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++); } /// printBranchInfo - Print conditional branch probabilities. @@ -694,29 +718,29 @@ void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, GCOVCoverage &Coverage, uint32_t &EdgeNo) { SmallVector<uint64_t, 16> BranchCounts; uint64_t TotalCounts = 0; - for (GCOVBlock::EdgeIterator I = Block.dst_begin(), E = Block.dst_end(); - I != E; ++I) { - const GCOVEdge *Edge = *I; + for (const GCOVEdge *Edge : Block.dsts()) { BranchCounts.push_back(Edge->Count); TotalCounts += Edge->Count; - if (Block.getCount()) ++Coverage.BranchesExec; - if (Edge->Count) ++Coverage.BranchesTaken; + if (Block.getCount()) + ++Coverage.BranchesExec; + if (Edge->Count) + ++Coverage.BranchesTaken; ++Coverage.Branches; if (Options.FuncCoverage) { const GCOVFunction *Function = &Block.getParent(); GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second; - if (Block.getCount()) ++FuncCoverage.BranchesExec; - if (Edge->Count) ++FuncCoverage.BranchesTaken; + if (Block.getCount()) + ++FuncCoverage.BranchesExec; + if (Edge->Count) + ++FuncCoverage.BranchesTaken; ++FuncCoverage.Branches; } } - for (SmallVectorImpl<uint64_t>::const_iterator I = BranchCounts.begin(), - E = BranchCounts.end(); I != E; ++I) { + for (uint64_t N : BranchCounts) OS << format("branch %2u ", EdgeNo++) - << formatBranchInfo(Options, *I, TotalCounts) << "\n"; - } + << formatBranchInfo(Options, N, TotalCounts) << "\n"; } /// printUncondBranchInfo - Print unconditional branch probabilities. @@ -728,46 +752,45 @@ void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, // printCoverage - Print generic coverage info used by both printFuncCoverage // and printFileCoverage. -void FileInfo::printCoverage(const GCOVCoverage &Coverage) const { - outs() << format("Lines executed:%.2f%% of %u\n", - double(Coverage.LinesExec)*100/Coverage.LogicalLines, - Coverage.LogicalLines); +void FileInfo::printCoverage(raw_ostream &OS, + const GCOVCoverage &Coverage) const { + OS << format("Lines executed:%.2f%% of %u\n", + double(Coverage.LinesExec) * 100 / Coverage.LogicalLines, + Coverage.LogicalLines); if (Options.BranchInfo) { if (Coverage.Branches) { - outs() << format("Branches executed:%.2f%% of %u\n", - double(Coverage.BranchesExec)*100/Coverage.Branches, - Coverage.Branches); - outs() << format("Taken at least once:%.2f%% of %u\n", - double(Coverage.BranchesTaken)*100/Coverage.Branches, - Coverage.Branches); + OS << format("Branches executed:%.2f%% of %u\n", + double(Coverage.BranchesExec) * 100 / Coverage.Branches, + Coverage.Branches); + OS << format("Taken at least once:%.2f%% of %u\n", + double(Coverage.BranchesTaken) * 100 / Coverage.Branches, + Coverage.Branches); } else { - outs() << "No branches\n"; + OS << "No branches\n"; } - outs() << "No calls\n"; // to be consistent with gcov + OS << "No calls\n"; // to be consistent with gcov } } // printFuncCoverage - Print per-function coverage info. -void FileInfo::printFuncCoverage() const { - for (FuncCoverageMap::const_iterator I = FuncCoverages.begin(), - E = FuncCoverages.end(); I != E; ++I) { - const GCOVCoverage &Coverage = I->second; - outs() << "Function '" << Coverage.Name << "'\n"; - printCoverage(Coverage); - outs() << "\n"; +void FileInfo::printFuncCoverage(raw_ostream &OS) const { + for (const auto &FC : FuncCoverages) { + const GCOVCoverage &Coverage = FC.second; + OS << "Function '" << Coverage.Name << "'\n"; + printCoverage(OS, Coverage); + OS << "\n"; } } // printFileCoverage - Print per-file coverage info. -void FileInfo::printFileCoverage() const { - for (FileCoverageList::const_iterator I = FileCoverages.begin(), - E = FileCoverages.end(); I != E; ++I) { - const std::string &Filename = I->first; - const GCOVCoverage &Coverage = I->second; - outs() << "File '" << Coverage.Name << "'\n"; - printCoverage(Coverage); +void FileInfo::printFileCoverage(raw_ostream &OS) const { + for (const auto &FC : FileCoverages) { + const std::string &Filename = FC.first; + const GCOVCoverage &Coverage = FC.second; + OS << "File '" << Coverage.Name << "'\n"; + printCoverage(OS, Coverage); if (!Options.NoOutput) - outs() << Coverage.Name << ":creating '" << Filename << "'\n"; - outs() << "\n"; + OS << Coverage.Name << ":creating '" << Filename << "'\n"; + OS << "\n"; } } diff --git a/contrib/llvm/lib/IR/Globals.cpp b/contrib/llvm/lib/IR/Globals.cpp index 54197d9..79a458c 100644 --- a/contrib/llvm/lib/IR/Globals.cpp +++ b/contrib/llvm/lib/IR/Globals.cpp @@ -38,12 +38,8 @@ bool GlobalValue::isDematerializable() const { std::error_code GlobalValue::materialize() { return getParent()->materialize(this); } -void GlobalValue::Dematerialize() { - getParent()->Dematerialize(this); -} - -const DataLayout *GlobalValue::getDataLayout() const { - return getParent()->getDataLayout(); +void GlobalValue::dematerialize() { + getParent()->dematerialize(this); } /// Override destroyConstant to make sure it doesn't get called on @@ -218,14 +214,20 @@ void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To, void GlobalVariable::setInitializer(Constant *InitVal) { if (!InitVal) { if (hasInitializer()) { + // Note, the num operands is used to compute the offset of the operand, so + // the order here matters. Clearing the operand then clearing the num + // operands ensures we have the correct offset to the operand. Op<0>().set(nullptr); - NumOperands = 0; + setGlobalVariableNumOperands(0); } } else { assert(InitVal->getType() == getType()->getElementType() && "Initializer type must match GlobalVariable type"); + // Note, the num operands is used to compute the offset of the operand, so + // the order here matters. We need to set num operands to 1 first so that + // we get the correct offset to the first operand when we set it. if (!hasInitializer()) - NumOperands = 1; + setGlobalVariableNumOperands(1); Op<0>().set(InitVal); } } @@ -245,40 +247,35 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { // GlobalAlias Implementation //===----------------------------------------------------------------------===// -GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, - const Twine &Name, Constant *Aliasee, - Module *ParentModule) - : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalAliasVal, - &Op<0>(), 1, Link, Name) { +GlobalAlias::GlobalAlias(PointerType *Ty, LinkageTypes Link, const Twine &Name, + Constant *Aliasee, Module *ParentModule) + : GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) { Op<0>() = Aliasee; if (ParentModule) ParentModule->getAliasList().push_back(this); } -GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, - LinkageTypes Link, const Twine &Name, - Constant *Aliasee, Module *ParentModule) { - return new GlobalAlias(Ty, AddressSpace, Link, Name, Aliasee, ParentModule); +GlobalAlias *GlobalAlias::create(PointerType *Ty, LinkageTypes Link, + const Twine &Name, Constant *Aliasee, + Module *ParentModule) { + return new GlobalAlias(Ty, Link, Name, Aliasee, ParentModule); } -GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Module *Parent) { - return create(Ty, AddressSpace, Linkage, Name, nullptr, Parent); +GlobalAlias *GlobalAlias::create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Module *Parent) { + return create(Ty, Linkage, Name, nullptr, Parent); } -GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - GlobalValue *Aliasee) { - return create(Ty, AddressSpace, Linkage, Name, Aliasee, Aliasee->getParent()); +GlobalAlias *GlobalAlias::create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, GlobalValue *Aliasee) { + return create(Ty, Linkage, Name, Aliasee, Aliasee->getParent()); } GlobalAlias *GlobalAlias::create(LinkageTypes Link, const Twine &Name, GlobalValue *Aliasee) { PointerType *PTy = Aliasee->getType(); - return create(PTy->getElementType(), PTy->getAddressSpace(), Link, Name, - Aliasee); + return create(PTy, Link, Name, Aliasee); } GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) { diff --git a/contrib/llvm/lib/IR/IRBuilder.cpp b/contrib/llvm/lib/IR/IRBuilder.cpp index ef1f226..bddb278 100644 --- a/contrib/llvm/lib/IR/IRBuilder.cpp +++ b/contrib/llvm/lib/IR/IRBuilder.cpp @@ -17,19 +17,23 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Statepoint.h" using namespace llvm; /// CreateGlobalString - Make a new global variable with an initializer that /// has array of i8 type filled in with the nul terminated string value /// specified. If Name is specified, it is the name of the global variable /// created. -Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) { +GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str, + const Twine &Name, + unsigned AddressSpace) { Constant *StrConstant = ConstantDataArray::getString(Context, Str); Module &M = *BB->getParent()->getParent(); GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), true, GlobalValue::PrivateLinkage, - StrConstant); - GV->setName(Name); + StrConstant, Name, nullptr, + GlobalVariable::NotThreadLocal, + AddressSpace); GV->setUnnamedAddr(true); return GV; } @@ -61,6 +65,19 @@ static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops, return CI; } +static InvokeInst *createInvokeHelper(Value *Invokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, + ArrayRef<Value *> Ops, + IRBuilderBase *Builder, + const Twine &Name = "") { + InvokeInst *II = + InvokeInst::Create(Invokee, NormalDest, UnwindDest, Ops, Name); + Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(), + II); + Builder->SetInstDebugLocation(II); + return II; +} + CallInst *IRBuilderBase:: CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, @@ -220,59 +237,104 @@ CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr, /// Create a call to a Masked intrinsic, with given intrinsic Id, /// an array of operands - Ops, and one overloaded type - DataTy -CallInst *IRBuilderBase::CreateMaskedIntrinsic(unsigned Id, +CallInst *IRBuilderBase::CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops, Type *DataTy, const Twine &Name) { Module *M = BB->getParent()->getParent(); Type *OverloadedTypes[] = { DataTy }; - Value *TheFn = Intrinsic::getDeclaration(M, (Intrinsic::ID)Id, OverloadedTypes); + Value *TheFn = Intrinsic::getDeclaration(M, Id, OverloadedTypes); return createCallHelper(TheFn, Ops, this, Name); } -CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee, - ArrayRef<Value*> CallArgs, - ArrayRef<Value*> DeoptArgs, - ArrayRef<Value*> GCArgs, - const Twine& Name) { - // Extract out the type of the callee. - PointerType *FuncPtrType = cast<PointerType>(ActualCallee->getType()); - assert(isa<FunctionType>(FuncPtrType->getElementType()) && - "actual callee must be a callable value"); +static std::vector<Value *> +getStatepointArgs(IRBuilderBase &B, uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, ArrayRef<Value *> CallArgs, + ArrayRef<Value *> DeoptArgs, ArrayRef<Value *> GCArgs) { + std::vector<Value *> Args; + Args.push_back(B.getInt64(ID)); + Args.push_back(B.getInt32(NumPatchBytes)); + Args.push_back(ActualCallee); + Args.push_back(B.getInt32(CallArgs.size())); + Args.push_back(B.getInt32((unsigned)StatepointFlags::None)); + Args.insert(Args.end(), CallArgs.begin(), CallArgs.end()); + Args.push_back(B.getInt32(0 /* no transition args */)); + Args.push_back(B.getInt32(DeoptArgs.size())); + Args.insert(Args.end(), DeoptArgs.begin(), DeoptArgs.end()); + Args.insert(Args.end(), GCArgs.begin(), GCArgs.end()); - - Module *M = BB->getParent()->getParent(); - // Fill in the one generic type'd argument (the function is also vararg) - Type *ArgTypes[] = { FuncPtrType }; - Function *FnStatepoint = - Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint, - ArgTypes); - - std::vector<llvm::Value *> args; - args.push_back(ActualCallee); - args.push_back(getInt32(CallArgs.size())); - args.push_back(getInt32(0 /*unused*/)); - args.insert(args.end(), CallArgs.begin(), CallArgs.end()); - args.push_back(getInt32(DeoptArgs.size())); - args.insert(args.end(), DeoptArgs.begin(), DeoptArgs.end()); - args.insert(args.end(), GCArgs.begin(), GCArgs.end()); - - return createCallHelper(FnStatepoint, args, this, Name); + return Args; +} + +CallInst *IRBuilderBase::CreateGCStatepointCall( + uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, + ArrayRef<Value *> CallArgs, ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name) { + // Extract out the type of the callee. + PointerType *FuncPtrType = cast<PointerType>(ActualCallee->getType()); + assert(isa<FunctionType>(FuncPtrType->getElementType()) && + "actual callee must be a callable value"); + + Module *M = BB->getParent()->getParent(); + // Fill in the one generic type'd argument (the function is also vararg) + Type *ArgTypes[] = { FuncPtrType }; + Function *FnStatepoint = + Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint, + ArgTypes); + + std::vector<llvm::Value *> Args = getStatepointArgs( + *this, ID, NumPatchBytes, ActualCallee, CallArgs, DeoptArgs, GCArgs); + return createCallHelper(FnStatepoint, Args, this, Name); +} + +CallInst *IRBuilderBase::CreateGCStatepointCall( + uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, + ArrayRef<Use> CallArgs, ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name) { + std::vector<Value *> VCallArgs; + for (auto &U : CallArgs) + VCallArgs.push_back(U.get()); + return CreateGCStatepointCall(ID, NumPatchBytes, ActualCallee, VCallArgs, + DeoptArgs, GCArgs, Name); +} + +InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( + uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, + BasicBlock *NormalDest, BasicBlock *UnwindDest, + ArrayRef<Value *> InvokeArgs, ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name) { + // Extract out the type of the callee. + PointerType *FuncPtrType = cast<PointerType>(ActualInvokee->getType()); + assert(isa<FunctionType>(FuncPtrType->getElementType()) && + "actual callee must be a callable value"); + + Module *M = BB->getParent()->getParent(); + // Fill in the one generic type'd argument (the function is also vararg) + Function *FnStatepoint = Intrinsic::getDeclaration( + M, Intrinsic::experimental_gc_statepoint, {FuncPtrType}); + + std::vector<llvm::Value *> Args = getStatepointArgs( + *this, ID, NumPatchBytes, ActualInvokee, InvokeArgs, DeoptArgs, GCArgs); + return createInvokeHelper(FnStatepoint, NormalDest, UnwindDest, Args, this, + Name); +} + +InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( + uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, + BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs, + ArrayRef<Value *> DeoptArgs, ArrayRef<Value *> GCArgs, const Twine &Name) { + std::vector<Value *> VCallArgs; + for (auto &U : InvokeArgs) + VCallArgs.push_back(U.get()); + return CreateGCStatepointInvoke(ID, NumPatchBytes, ActualInvokee, NormalDest, + UnwindDest, VCallArgs, DeoptArgs, GCArgs, + Name); } CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint, Type *ResultType, const Twine &Name) { - Intrinsic::ID ID; - if (ResultType->isIntegerTy()) { - ID = Intrinsic::experimental_gc_result_int; - } else if (ResultType->isFloatingPointTy()) { - ID = Intrinsic::experimental_gc_result_float; - } else if (ResultType->isPointerTy()) { - ID = Intrinsic::experimental_gc_result_ptr; - } else { - llvm_unreachable("unimplemented result type for gc.result"); - } + Intrinsic::ID ID = Intrinsic::experimental_gc_result; Module *M = BB->getParent()->getParent(); Type *Types[] = {ResultType}; Value *FnGCResult = Intrinsic::getDeclaration(M, ID, Types); diff --git a/contrib/llvm/lib/IR/IRPrintingPasses.cpp b/contrib/llvm/lib/IR/IRPrintingPasses.cpp index 91ccfbb..03e7d55 100644 --- a/contrib/llvm/lib/IR/IRPrintingPasses.cpp +++ b/contrib/llvm/lib/IR/IRPrintingPasses.cpp @@ -21,11 +21,14 @@ using namespace llvm; PrintModulePass::PrintModulePass() : OS(dbgs()) {} -PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner) - : OS(OS), Banner(Banner) {} +PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner, + bool ShouldPreserveUseListOrder) + : OS(OS), Banner(Banner), + ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {} PreservedAnalyses PrintModulePass::run(Module &M) { - OS << Banner << M; + OS << Banner; + M.print(OS, nullptr, ShouldPreserveUseListOrder); return PreservedAnalyses::all(); } @@ -46,8 +49,9 @@ class PrintModulePassWrapper : public ModulePass { public: static char ID; PrintModulePassWrapper() : ModulePass(ID) {} - PrintModulePassWrapper(raw_ostream &OS, const std::string &Banner) - : ModulePass(ID), P(OS, Banner) {} + PrintModulePassWrapper(raw_ostream &OS, const std::string &Banner, + bool ShouldPreserveUseListOrder) + : ModulePass(ID), P(OS, Banner, ShouldPreserveUseListOrder) {} bool runOnModule(Module &M) override { P.run(M); @@ -99,7 +103,7 @@ public: } }; -} +} // namespace char PrintModulePassWrapper::ID = 0; INITIALIZE_PASS(PrintModulePassWrapper, "print-module", @@ -112,8 +116,9 @@ INITIALIZE_PASS(PrintBasicBlockPass, "print-bb", "Print BB to stderr", false, false) ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS, - const std::string &Banner) { - return new PrintModulePassWrapper(OS, Banner); + const std::string &Banner, + bool ShouldPreserveUseListOrder) { + return new PrintModulePassWrapper(OS, Banner, ShouldPreserveUseListOrder); } FunctionPass *llvm::createPrintFunctionPass(llvm::raw_ostream &OS, diff --git a/contrib/llvm/lib/IR/InlineAsm.cpp b/contrib/llvm/lib/IR/InlineAsm.cpp index 16d874f3..aa9e027 100644 --- a/contrib/llvm/lib/IR/InlineAsm.cpp +++ b/contrib/llvm/lib/IR/InlineAsm.cpp @@ -73,9 +73,9 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str, unsigned multipleAlternativeCount = Str.count('|') + 1; unsigned multipleAlternativeIndex = 0; ConstraintCodeVector *pCodes = &Codes; - + // Initialize - isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false); + isMultipleAlternative = multipleAlternativeCount > 1; if (isMultipleAlternative) { multipleAlternatives.resize(multipleAlternativeCount); pCodes = &multipleAlternatives[0].Codes; @@ -99,12 +99,12 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str, ++I; Type = isOutput; } - + if (*I == '*') { isIndirect = true; ++I; } - + if (I == E) return true; // Just a prefix, like "==" or "~". // Parse the modifiers. @@ -167,7 +167,9 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str, // Note that operand #n has a matching input. scInfo.MatchingInput = ConstraintsSoFar.size(); } else { - if (ConstraintsSoFar[N].hasMatchingInput()) + if (ConstraintsSoFar[N].hasMatchingInput() && + (size_t)ConstraintsSoFar[N].MatchingInput != + ConstraintsSoFar.size()) return true; // Note that operand #n has a matching input. ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); @@ -228,7 +230,10 @@ InlineAsm::ParseConstraints(StringRef Constraints) { I = ConstraintEnd; if (I != E) { ++I; - if (I == E) { Result.clear(); break; } // don't allow "xyz," + if (I == E) { + Result.clear(); + break; + } // don't allow "xyz," } } diff --git a/contrib/llvm/lib/IR/Instruction.cpp b/contrib/llvm/lib/IR/Instruction.cpp index 92c6e9f..af42638 100644 --- a/contrib/llvm/lib/IR/Instruction.cpp +++ b/contrib/llvm/lib/IR/Instruction.cpp @@ -26,16 +26,12 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, // If requested, insert this instruction into a basic block... if (InsertBefore) { - assert(InsertBefore->getParent() && - "Instruction to insert before is not in a basic block!"); - InsertBefore->getParent()->getInstList().insert(InsertBefore, this); + BasicBlock *BB = InsertBefore->getParent(); + assert(BB && "Instruction to insert before is not in a basic block!"); + BB->getInstList().insert(InsertBefore, this); } } -const DataLayout *Instruction::getDataLayout() const { - return getParent()->getDataLayout(); -} - Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) { @@ -58,12 +54,21 @@ void Instruction::setParent(BasicBlock *P) { Parent = P; } +const Module *Instruction::getModule() const { + return getParent()->getModule(); +} + +Module *Instruction::getModule() { + return getParent()->getModule(); +} + + void Instruction::removeFromParent() { getParent()->getInstList().remove(this); } -void Instruction::eraseFromParent() { - getParent()->getInstList().erase(this); +iplist<Instruction>::iterator Instruction::eraseFromParent() { + return getParent()->getInstList().erase(this); } /// insertBefore - Insert an unlinked instructions into a basic block diff --git a/contrib/llvm/lib/IR/Instructions.cpp b/contrib/llvm/lib/IR/Instructions.cpp index 132800e..d45b511 100644 --- a/contrib/llvm/lib/IR/Instructions.cpp +++ b/contrib/llvm/lib/IR/Instructions.cpp @@ -85,30 +85,14 @@ const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) { //===----------------------------------------------------------------------===// PHINode::PHINode(const PHINode &PN) - : Instruction(PN.getType(), Instruction::PHI, - allocHungoffUses(PN.getNumOperands()), PN.getNumOperands()), - ReservedSpace(PN.getNumOperands()) { + : Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()), + ReservedSpace(PN.getNumOperands()) { + allocHungoffUses(PN.getNumOperands()); std::copy(PN.op_begin(), PN.op_end(), op_begin()); std::copy(PN.block_begin(), PN.block_end(), block_begin()); SubclassOptionalData = PN.SubclassOptionalData; } -PHINode::~PHINode() { - dropHungoffUses(); -} - -Use *PHINode::allocHungoffUses(unsigned N) const { - // Allocate the array of Uses of the incoming values, followed by a pointer - // (with bottom bit set) to the User, followed by the array of pointers to - // the incoming basic blocks. - size_t size = N * sizeof(Use) + sizeof(Use::UserRef) - + N * sizeof(BasicBlock*); - Use *Begin = static_cast<Use*>(::operator new(size)); - Use *End = Begin + N; - (void) new(End) Use::UserRef(const_cast<PHINode*>(this), 1); - return Use::initTags(Begin, End); -} - // removeIncomingValue - Remove an incoming value. This is useful if a // predecessor basic block is deleted. Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) { @@ -124,7 +108,7 @@ Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) { // Nuke the last value. Op<-1>().set(nullptr); - --NumOperands; + setNumHungOffUseOperands(getNumOperands() - 1); // If the PHI node is dead, because it has zero entries, nuke it now. if (getNumOperands() == 0 && DeletePHIIfEmpty) { @@ -144,16 +128,8 @@ void PHINode::growOperands() { unsigned NumOps = e + e / 2; if (NumOps < 2) NumOps = 2; // 2 op PHI nodes are VERY common. - Use *OldOps = op_begin(); - BasicBlock **OldBlocks = block_begin(); - ReservedSpace = NumOps; - OperandList = allocHungoffUses(ReservedSpace); - - std::copy(OldOps, OldOps + e, op_begin()); - std::copy(OldBlocks, OldBlocks + e, block_begin()); - - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace, /* IsPhi */ true); } /// hasConstantValue - If the specified PHI node always merges together the same @@ -177,57 +153,47 @@ Value *PHINode::hasConstantValue() const { // LandingPadInst Implementation //===----------------------------------------------------------------------===// -LandingPadInst::LandingPadInst(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedValues, const Twine &NameStr, - Instruction *InsertBefore) - : Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertBefore) { - init(PersonalityFn, 1 + NumReservedValues, NameStr); +LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues, + const Twine &NameStr, Instruction *InsertBefore) + : Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertBefore) { + init(NumReservedValues, NameStr); } -LandingPadInst::LandingPadInst(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedValues, const Twine &NameStr, - BasicBlock *InsertAtEnd) - : Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertAtEnd) { - init(PersonalityFn, 1 + NumReservedValues, NameStr); +LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertAtEnd) { + init(NumReservedValues, NameStr); } LandingPadInst::LandingPadInst(const LandingPadInst &LP) - : Instruction(LP.getType(), Instruction::LandingPad, - allocHungoffUses(LP.getNumOperands()), LP.getNumOperands()), - ReservedSpace(LP.getNumOperands()) { - Use *OL = OperandList, *InOL = LP.OperandList; + : Instruction(LP.getType(), Instruction::LandingPad, nullptr, + LP.getNumOperands()), + ReservedSpace(LP.getNumOperands()) { + allocHungoffUses(LP.getNumOperands()); + Use *OL = getOperandList(); + const Use *InOL = LP.getOperandList(); for (unsigned I = 0, E = ReservedSpace; I != E; ++I) OL[I] = InOL[I]; setCleanup(LP.isCleanup()); } -LandingPadInst::~LandingPadInst() { - dropHungoffUses(); -} - -LandingPadInst *LandingPadInst::Create(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedClauses, +LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses, const Twine &NameStr, Instruction *InsertBefore) { - return new LandingPadInst(RetTy, PersonalityFn, NumReservedClauses, NameStr, - InsertBefore); + return new LandingPadInst(RetTy, NumReservedClauses, NameStr, InsertBefore); } -LandingPadInst *LandingPadInst::Create(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedClauses, +LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new LandingPadInst(RetTy, PersonalityFn, NumReservedClauses, NameStr, - InsertAtEnd); + return new LandingPadInst(RetTy, NumReservedClauses, NameStr, InsertAtEnd); } -void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues, - const Twine &NameStr) { +void LandingPadInst::init(unsigned NumReservedValues, const Twine &NameStr) { ReservedSpace = NumReservedValues; - NumOperands = 1; - OperandList = allocHungoffUses(ReservedSpace); - OperandList[0] = PersFn; + setNumHungOffUseOperands(0); + allocHungoffUses(ReservedSpace); setName(NameStr); setCleanup(false); } @@ -237,23 +203,16 @@ void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues, void LandingPadInst::growOperands(unsigned Size) { unsigned e = getNumOperands(); if (ReservedSpace >= e + Size) return; - ReservedSpace = (e + Size / 2) * 2; - - Use *NewOps = allocHungoffUses(ReservedSpace); - Use *OldOps = OperandList; - for (unsigned i = 0; i != e; ++i) - NewOps[i] = OldOps[i]; - - OperandList = NewOps; - Use::zap(OldOps, OldOps + e, true); + ReservedSpace = (std::max(e, 1U) + Size / 2) * 2; + growHungoffUses(ReservedSpace); } void LandingPadInst::addClause(Constant *Val) { unsigned OpNo = getNumOperands(); growOperands(1); assert(OpNo < ReservedSpace && "Growing didn't work!"); - ++NumOperands; - OperandList[OpNo] = Val; + setNumHungOffUseOperands(getNumOperands() + 1); + getOperandList()[OpNo] = Val; } //===----------------------------------------------------------------------===// @@ -263,14 +222,13 @@ void LandingPadInst::addClause(Constant *Val) { CallInst::~CallInst() { } -void CallInst::init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) { - assert(NumOperands == Args.size() + 1 && "NumOperands not set up?"); +void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr) { + this->FTy = FTy; + assert(getNumOperands() == Args.size() + 1 && "NumOperands not set up?"); Op<-1>() = Func; #ifndef NDEBUG - FunctionType *FTy = - cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); - assert((Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Calling a function with bad signature!"); @@ -286,15 +244,12 @@ void CallInst::init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) { } void CallInst::init(Value *Func, const Twine &NameStr) { - assert(NumOperands == 1 && "NumOperands not set up?"); + FTy = + cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); + assert(getNumOperands() == 1 && "NumOperands not set up?"); Op<-1>() = Func; -#ifndef NDEBUG - FunctionType *FTy = - cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); - assert(FTy->getNumParams() == 0 && "Calling a function with bad signature"); -#endif setName(NameStr); } @@ -320,10 +275,10 @@ CallInst::CallInst(Value *Func, const Twine &Name, } CallInst::CallInst(const CallInst &CI) - : Instruction(CI.getType(), Instruction::Call, - OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(), - CI.getNumOperands()) { - setAttributes(CI.getAttributes()); + : Instruction(CI.getType(), Instruction::Call, + OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(), + CI.getNumOperands()), + AttributeList(CI.AttributeList), FTy(CI.FTy) { setTailCallKind(CI.getTailCallKind()); setCallingConv(CI.getCallingConv()); @@ -346,6 +301,18 @@ void CallInst::removeAttribute(unsigned i, Attribute attr) { setAttributes(PAL); } +void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); + setAttributes(PAL); +} + +void CallInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); + setAttributes(PAL); +} + bool CallInst::hasFnAttrImpl(Attribute::AttrKind A) const { if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) return true; @@ -529,17 +496,17 @@ Instruction* CallInst::CreateFree(Value* Source, BasicBlock *InsertAtEnd) { // InvokeInst Implementation //===----------------------------------------------------------------------===// -void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef<Value *> Args, const Twine &NameStr) { - assert(NumOperands == 3 + Args.size() && "NumOperands not set up?"); +void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + const Twine &NameStr) { + this->FTy = FTy; + + assert(getNumOperands() == 3 + Args.size() && "NumOperands not set up?"); Op<-3>() = Fn; Op<-2>() = IfNormal; Op<-1>() = IfException; #ifndef NDEBUG - FunctionType *FTy = - cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()); - assert(((Args.size() == FTy->getNumParams()) || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Invoking a function with bad signature"); @@ -555,11 +522,11 @@ void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, } InvokeInst::InvokeInst(const InvokeInst &II) - : TerminatorInst(II.getType(), Instruction::Invoke, - OperandTraits<InvokeInst>::op_end(this) - - II.getNumOperands(), - II.getNumOperands()) { - setAttributes(II.getAttributes()); + : TerminatorInst(II.getType(), Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - + II.getNumOperands(), + II.getNumOperands()), + AttributeList(II.AttributeList), FTy(II.FTy) { setCallingConv(II.getCallingConv()); std::copy(II.op_begin(), II.op_end(), op_begin()); SubclassOptionalData = II.SubclassOptionalData; @@ -605,6 +572,18 @@ void InvokeInst::removeAttribute(unsigned i, Attribute attr) { setAttributes(PAL); } +void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); + setAttributes(PAL); +} + +void InvokeInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { + AttributeSet PAL = getAttributes(); + PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); + setAttributes(PAL); +} + LandingPadInst *InvokeInst::getLandingPadInst() const { return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI()); } @@ -829,46 +808,25 @@ static Value *getAISize(LLVMContext &Context, Value *Amt) { return Amt; } -AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, - const Twine &Name, Instruction *InsertBefore) - : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, - getAISize(Ty->getContext(), ArraySize), InsertBefore) { - setAlignment(0); - assert(!Ty->isVoidTy() && "Cannot allocate void!"); - setName(Name); -} +AllocaInst::AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore) + : AllocaInst(Ty, /*ArraySize=*/nullptr, Name, InsertBefore) {} -AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, - const Twine &Name, BasicBlock *InsertAtEnd) - : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, - getAISize(Ty->getContext(), ArraySize), InsertAtEnd) { - setAlignment(0); - assert(!Ty->isVoidTy() && "Cannot allocate void!"); - setName(Name); -} +AllocaInst::AllocaInst(Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd) + : AllocaInst(Ty, /*ArraySize=*/nullptr, Name, InsertAtEnd) {} -AllocaInst::AllocaInst(Type *Ty, const Twine &Name, +AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, const Twine &Name, Instruction *InsertBefore) - : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, - getAISize(Ty->getContext(), nullptr), InsertBefore) { - setAlignment(0); - assert(!Ty->isVoidTy() && "Cannot allocate void!"); - setName(Name); -} + : AllocaInst(Ty, ArraySize, /*Align=*/0, Name, InsertBefore) {} -AllocaInst::AllocaInst(Type *Ty, const Twine &Name, +AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, const Twine &Name, BasicBlock *InsertAtEnd) - : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, - getAISize(Ty->getContext(), nullptr), InsertAtEnd) { - setAlignment(0); - assert(!Ty->isVoidTy() && "Cannot allocate void!"); - setName(Name); -} + : AllocaInst(Ty, ArraySize, /*Align=*/0, Name, InsertAtEnd) {} AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, const Twine &Name, Instruction *InsertBefore) - : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, - getAISize(Ty->getContext(), ArraySize), InsertBefore) { + : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, + getAISize(Ty->getContext(), ArraySize), InsertBefore), + AllocatedType(Ty) { setAlignment(Align); assert(!Ty->isVoidTy() && "Cannot allocate void!"); setName(Name); @@ -876,8 +834,9 @@ AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, AllocaInst::AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, const Twine &Name, BasicBlock *InsertAtEnd) - : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, - getAISize(Ty->getContext(), ArraySize), InsertAtEnd) { + : UnaryInstruction(PointerType::getUnqual(Ty), Alloca, + getAISize(Ty->getContext(), ArraySize), InsertAtEnd), + AllocatedType(Ty) { setAlignment(Align); assert(!Ty->isVoidTy() && "Cannot allocate void!"); setName(Name); @@ -902,10 +861,6 @@ bool AllocaInst::isArrayAllocation() const { return true; } -Type *AllocaInst::getAllocatedType() const { - return getType()->getElementType(); -} - /// isStaticAlloca - Return true if this alloca is in the entry block of the /// function and is a constant size. If so, the code generator will fold it /// into the prolog/epilog code, so it is basically free. @@ -930,75 +885,34 @@ void LoadInst::AssertOK() { } LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertBef) { - setVolatile(false); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); - setName(Name); -} + : LoadInst(Ptr, Name, /*isVolatile=*/false, InsertBef) {} LoadInst::LoadInst(Value *Ptr, const Twine &Name, BasicBlock *InsertAE) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertAE) { - setVolatile(false); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); - setName(Name); -} + : LoadInst(Ptr, Name, /*isVolatile=*/false, InsertAE) {} -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, Instruction *InsertBef) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertBef) { - setVolatile(isVolatile); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); - setName(Name); -} + : LoadInst(Ty, Ptr, Name, isVolatile, /*Align=*/0, InsertBef) {} LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, BasicBlock *InsertAE) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertAE) { - setVolatile(isVolatile); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); - setName(Name); -} + : LoadInst(Ptr, Name, isVolatile, /*Align=*/0, InsertAE) {} -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, unsigned Align, Instruction *InsertBef) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertBef) { - setVolatile(isVolatile); - setAlignment(Align); - setAtomic(NotAtomic); - AssertOK(); - setName(Name); -} + : LoadInst(Ty, Ptr, Name, isVolatile, Align, NotAtomic, CrossThread, + InsertBef) {} -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, +LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, unsigned Align, BasicBlock *InsertAE) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertAE) { - setVolatile(isVolatile); - setAlignment(Align); - setAtomic(NotAtomic); - AssertOK(); - setName(Name); + : LoadInst(Ptr, Name, isVolatile, Align, NotAtomic, CrossThread, InsertAE) { } -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, unsigned Align, AtomicOrdering Order, - SynchronizationScope SynchScope, - Instruction *InsertBef) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertBef) { + SynchronizationScope SynchScope, Instruction *InsertBef) + : UnaryInstruction(Ty, Load, Ptr, InsertBef) { + assert(Ty == cast<PointerType>(Ptr->getType())->getElementType()); setVolatile(isVolatile); setAlignment(Align); setAtomic(Order, SynchScope); @@ -1039,10 +953,10 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, BasicBlock *InsertAE) if (Name && Name[0]) setName(Name); } -LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const char *Name, bool isVolatile, Instruction *InsertBef) -: UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertBef) { + : UnaryInstruction(Ty, Load, Ptr, InsertBef) { + assert(Ty == cast<PointerType>(Ptr->getType())->getElementType()); setVolatile(isVolatile); setAlignment(0); setAtomic(NotAtomic); @@ -1085,60 +999,29 @@ void StoreInst::AssertOK() { "Alignment required for atomic store"); } - StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore) - : Instruction(Type::getVoidTy(val->getContext()), Store, - OperandTraits<StoreInst>::op_begin(this), - OperandTraits<StoreInst>::operands(this), - InsertBefore) { - Op<0>() = val; - Op<1>() = addr; - setVolatile(false); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); -} + : StoreInst(val, addr, /*isVolatile=*/false, InsertBefore) {} StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd) - : Instruction(Type::getVoidTy(val->getContext()), Store, - OperandTraits<StoreInst>::op_begin(this), - OperandTraits<StoreInst>::operands(this), - InsertAtEnd) { - Op<0>() = val; - Op<1>() = addr; - setVolatile(false); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); -} + : StoreInst(val, addr, /*isVolatile=*/false, InsertAtEnd) {} StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, Instruction *InsertBefore) - : Instruction(Type::getVoidTy(val->getContext()), Store, - OperandTraits<StoreInst>::op_begin(this), - OperandTraits<StoreInst>::operands(this), - InsertBefore) { - Op<0>() = val; - Op<1>() = addr; - setVolatile(isVolatile); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); -} + : StoreInst(val, addr, isVolatile, /*Align=*/0, InsertBefore) {} StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, - unsigned Align, Instruction *InsertBefore) - : Instruction(Type::getVoidTy(val->getContext()), Store, - OperandTraits<StoreInst>::op_begin(this), - OperandTraits<StoreInst>::operands(this), - InsertBefore) { - Op<0>() = val; - Op<1>() = addr; - setVolatile(isVolatile); - setAlignment(Align); - setAtomic(NotAtomic); - AssertOK(); -} + BasicBlock *InsertAtEnd) + : StoreInst(val, addr, isVolatile, /*Align=*/0, InsertAtEnd) {} + +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align, + Instruction *InsertBefore) + : StoreInst(val, addr, isVolatile, Align, NotAtomic, CrossThread, + InsertBefore) {} + +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align, + BasicBlock *InsertAtEnd) + : StoreInst(val, addr, isVolatile, Align, NotAtomic, CrossThread, + InsertAtEnd) {} StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align, AtomicOrdering Order, @@ -1157,34 +1040,6 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, } StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, - BasicBlock *InsertAtEnd) - : Instruction(Type::getVoidTy(val->getContext()), Store, - OperandTraits<StoreInst>::op_begin(this), - OperandTraits<StoreInst>::operands(this), - InsertAtEnd) { - Op<0>() = val; - Op<1>() = addr; - setVolatile(isVolatile); - setAlignment(0); - setAtomic(NotAtomic); - AssertOK(); -} - -StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, - unsigned Align, BasicBlock *InsertAtEnd) - : Instruction(Type::getVoidTy(val->getContext()), Store, - OperandTraits<StoreInst>::op_begin(this), - OperandTraits<StoreInst>::operands(this), - InsertAtEnd) { - Op<0>() = val; - Op<1>() = addr; - setVolatile(isVolatile); - setAlignment(Align); - setAtomic(NotAtomic); - AssertOK(); -} - -StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope, BasicBlock *InsertAtEnd) @@ -1342,17 +1197,20 @@ FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering, void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name) { - assert(NumOperands == 1 + IdxList.size() && "NumOperands not initialized?"); - OperandList[0] = Ptr; + assert(getNumOperands() == 1 + IdxList.size() && + "NumOperands not initialized?"); + Op<0>() = Ptr; std::copy(IdxList.begin(), IdxList.end(), op_begin() + 1); setName(Name); } GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI) - : Instruction(GEPI.getType(), GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - - GEPI.getNumOperands(), - GEPI.getNumOperands()) { + : Instruction(GEPI.getType(), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - + GEPI.getNumOperands(), + GEPI.getNumOperands()), + SourceElementType(GEPI.SourceElementType), + ResultElementType(GEPI.ResultElementType) { std::copy(GEPI.op_begin(), GEPI.op_end(), op_begin()); SubclassOptionalData = GEPI.SubclassOptionalData; } @@ -1367,11 +1225,7 @@ GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI) /// pointer type. /// template <typename IndexTy> -static Type *getIndexedTypeInternal(Type *Ptr, ArrayRef<IndexTy> IdxList) { - PointerType *PTy = dyn_cast<PointerType>(Ptr->getScalarType()); - if (!PTy) return nullptr; // Type isn't a pointer type! - Type *Agg = PTy->getElementType(); - +static Type *getIndexedTypeInternal(Type *Agg, ArrayRef<IndexTy> IdxList) { // Handle the special case of the empty set index set, which is always valid. if (IdxList.empty()) return Agg; @@ -1392,17 +1246,17 @@ static Type *getIndexedTypeInternal(Type *Ptr, ArrayRef<IndexTy> IdxList) { return CurIdx == IdxList.size() ? Agg : nullptr; } -Type *GetElementPtrInst::getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList) { - return getIndexedTypeInternal(Ptr, IdxList); +Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<Value *> IdxList) { + return getIndexedTypeInternal(Ty, IdxList); } -Type *GetElementPtrInst::getIndexedType(Type *Ptr, +Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<Constant *> IdxList) { - return getIndexedTypeInternal(Ptr, IdxList); + return getIndexedTypeInternal(Ty, IdxList); } -Type *GetElementPtrInst::getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList) { - return getIndexedTypeInternal(Ptr, IdxList); +Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList) { + return getIndexedTypeInternal(Ty, IdxList); } /// hasAllZeroIndices - Return true if all of the indices of this GEP are @@ -1657,7 +1511,7 @@ void ShuffleVectorInst::getShuffleMask(Constant *Mask, void InsertValueInst::init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, const Twine &Name) { - assert(NumOperands == 2 && "NumOperands not initialized?"); + assert(getNumOperands() == 2 && "NumOperands not initialized?"); // There's no fundamental reason why we require at least one index // (other than weirdness with &*IdxBegin being invalid; see @@ -1688,7 +1542,7 @@ InsertValueInst::InsertValueInst(const InsertValueInst &IVI) //===----------------------------------------------------------------------===// void ExtractValueInst::init(ArrayRef<unsigned> Idxs, const Twine &Name) { - assert(NumOperands == 1 && "NumOperands not initialized?"); + assert(getNumOperands() == 1 && "NumOperands not initialized?"); // There's no fundamental reason why we require at least one index. // But there's no present need to support it. @@ -2157,21 +2011,15 @@ bool CastInst::isNoopCast(Type *IntPtrTy) const { return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy); } -bool CastInst::isNoopCast(const DataLayout *DL) const { - if (!DL) { - // Assume maximum pointer size. - return isNoopCast(Type::getInt64Ty(getContext())); - } - +bool CastInst::isNoopCast(const DataLayout &DL) const { Type *PtrOpTy = nullptr; if (getOpcode() == Instruction::PtrToInt) PtrOpTy = getOperand(0)->getType(); else if (getOpcode() == Instruction::IntToPtr) PtrOpTy = getType(); - Type *IntPtrTy = PtrOpTy - ? DL->getIntPtrType(PtrOpTy) - : DL->getIntPtrType(getContext(), 0); + Type *IntPtrTy = + PtrOpTy ? DL.getIntPtrType(PtrOpTy) : DL.getIntPtrType(getContext(), 0); return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy); } @@ -2227,13 +2075,13 @@ unsigned CastInst::isEliminableCastPair( // N X X U S F F N X N 2 V V | // C T T I I P P C T T P T T -+ { 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // Trunc -+ - { 8, 1, 9,99,99, 2, 0,99,99,99, 2, 3, 0}, // ZExt | + { 8, 1, 9,99,99, 2,17,99,99,99, 2, 3, 0}, // ZExt | { 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3, 0}, // SExt | { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToUI | { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToSI | { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // UIToFP +- firstOp { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // SIToFP | - { 99,99,99, 0, 0,99,99, 1, 0,99,99, 4, 0}, // FPTrunc | + { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // FPTrunc | { 99,99,99, 2, 2,99,99,10, 2,99,99, 4, 0}, // FPExt | { 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3, 0}, // PtrToInt | { 99,99,99,99,99,99,99,99,99,11,99,15, 0}, // IntToPtr | @@ -2394,6 +2242,9 @@ unsigned CastInst::isEliminableCastPair( "Illegal bitcast, ptrtoint sequence!"); // Allowed, use second cast's opcode return secondOp; + case 17: + // (sitofp (zext x)) -> (uitofp x) + return Instruction::UIToFP; case 99: // Cast combination can't happen (error in input). This is for all cases // where the MidTy is not the same for the two cast instructions. @@ -2644,44 +2495,38 @@ bool CastInst::isCastable(Type *SrcTy, Type *DestTy) { // Run through the possibilities ... if (DestTy->isIntegerTy()) { // Casting to integral - if (SrcTy->isIntegerTy()) { // Casting from integral + if (SrcTy->isIntegerTy()) // Casting from integral return true; - } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt + if (SrcTy->isFloatingPointTy()) // Casting from floating pt return true; - } else if (SrcTy->isVectorTy()) { // Casting from vector + if (SrcTy->isVectorTy()) // Casting from vector return DestBits == SrcBits; - } else { // Casting from something else - return SrcTy->isPointerTy(); - } - } else if (DestTy->isFloatingPointTy()) { // Casting to floating pt - if (SrcTy->isIntegerTy()) { // Casting from integral + // Casting from something else + return SrcTy->isPointerTy(); + } + if (DestTy->isFloatingPointTy()) { // Casting to floating pt + if (SrcTy->isIntegerTy()) // Casting from integral return true; - } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt + if (SrcTy->isFloatingPointTy()) // Casting from floating pt return true; - } else if (SrcTy->isVectorTy()) { // Casting from vector + if (SrcTy->isVectorTy()) // Casting from vector return DestBits == SrcBits; - } else { // Casting from something else - return false; - } - } else if (DestTy->isVectorTy()) { // Casting to vector + // Casting from something else + return false; + } + if (DestTy->isVectorTy()) // Casting to vector return DestBits == SrcBits; - } else if (DestTy->isPointerTy()) { // Casting to pointer - if (SrcTy->isPointerTy()) { // Casting from pointer - return true; - } else if (SrcTy->isIntegerTy()) { // Casting from integral + if (DestTy->isPointerTy()) { // Casting to pointer + if (SrcTy->isPointerTy()) // Casting from pointer return true; - } else { // Casting from something else - return false; - } - } else if (DestTy->isX86_MMXTy()) { - if (SrcTy->isVectorTy()) { + return SrcTy->isIntegerTy(); // Casting from integral + } + if (DestTy->isX86_MMXTy()) { + if (SrcTy->isVectorTy()) return DestBits == SrcBits; // 64-bit vector to MMX - } else { - return false; - } - } else { // Casting to something else return false; - } + } // Casting to something else + return false; } bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) { @@ -2725,13 +2570,13 @@ bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) { } bool CastInst::isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, - const DataLayout *DL) { + const DataLayout &DL) { if (auto *PtrTy = dyn_cast<PointerType>(SrcTy)) if (auto *IntTy = dyn_cast<IntegerType>(DestTy)) - return DL && IntTy->getBitWidth() == DL->getPointerTypeSizeInBits(PtrTy); + return IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy); if (auto *PtrTy = dyn_cast<PointerType>(DestTy)) if (auto *IntTy = dyn_cast<IntegerType>(SrcTy)) - return DL && IntTy->getBitWidth() == DL->getPointerTypeSizeInBits(PtrTy); + return IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy); return isBitCastable(SrcTy, DestTy); } @@ -2852,10 +2697,6 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) { // Check for type sanity on the arguments Type *SrcTy = S->getType(); - // If this is a cast to the same type then it's trivially true. - if (SrcTy == DstTy) - return true; - if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType() || SrcTy->isAggregateType() || DstTy->isAggregateType()) return false; @@ -3415,11 +3256,11 @@ bool CmpInst::isFalseWhenEqual(unsigned short predicate) { void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumReserved) { assert(Value && Default && NumReserved); ReservedSpace = NumReserved; - NumOperands = 2; - OperandList = allocHungoffUses(ReservedSpace); + setNumHungOffUseOperands(2); + allocHungoffUses(ReservedSpace); - OperandList[0] = Value; - OperandList[1] = Default; + Op<0>() = Value; + Op<1>() = Default; } /// SwitchInst ctor - Create a new switch instruction, specifying a value to @@ -3447,8 +3288,9 @@ SwitchInst::SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, SwitchInst::SwitchInst(const SwitchInst &SI) : TerminatorInst(SI.getType(), Instruction::Switch, nullptr, 0) { init(SI.getCondition(), SI.getDefaultDest(), SI.getNumOperands()); - NumOperands = SI.getNumOperands(); - Use *OL = OperandList, *InOL = SI.OperandList; + setNumHungOffUseOperands(SI.getNumOperands()); + Use *OL = getOperandList(); + const Use *InOL = SI.getOperandList(); for (unsigned i = 2, E = SI.getNumOperands(); i != E; i += 2) { OL[i] = InOL[i]; OL[i+1] = InOL[i+1]; @@ -3456,21 +3298,17 @@ SwitchInst::SwitchInst(const SwitchInst &SI) SubclassOptionalData = SI.SubclassOptionalData; } -SwitchInst::~SwitchInst() { - dropHungoffUses(); -} - /// addCase - Add an entry to the switch instruction... /// void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { - unsigned NewCaseIdx = getNumCases(); - unsigned OpNo = NumOperands; + unsigned NewCaseIdx = getNumCases(); + unsigned OpNo = getNumOperands(); if (OpNo+2 > ReservedSpace) growOperands(); // Get more space! // Initialize some new operands. assert(OpNo+1 < ReservedSpace && "Growing didn't work!"); - NumOperands = OpNo+2; + setNumHungOffUseOperands(OpNo+2); CaseIt Case(this, NewCaseIdx); Case.setValue(OnVal); Case.setSuccessor(Dest); @@ -3484,7 +3322,7 @@ void SwitchInst::removeCase(CaseIt i) { assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!"); unsigned NumOps = getNumOperands(); - Use *OL = OperandList; + Use *OL = getOperandList(); // Overwrite this case with the end of the list. if (2 + (idx + 1) * 2 != NumOps) { @@ -3495,7 +3333,7 @@ void SwitchInst::removeCase(CaseIt i) { // Nuke the last value. OL[NumOps-2].set(nullptr); OL[NumOps-2+1].set(nullptr); - NumOperands = NumOps-2; + setNumHungOffUseOperands(NumOps-2); } /// growOperands - grow operands - This grows the operand list in response @@ -3506,13 +3344,7 @@ void SwitchInst::growOperands() { unsigned NumOps = e*3; ReservedSpace = NumOps; - Use *NewOps = allocHungoffUses(NumOps); - Use *OldOps = OperandList; - for (unsigned i = 0; i != e; ++i) { - NewOps[i] = OldOps[i]; - } - OperandList = NewOps; - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace); } @@ -3534,10 +3366,10 @@ void IndirectBrInst::init(Value *Address, unsigned NumDests) { assert(Address && Address->getType()->isPointerTy() && "Address of indirectbr must be a pointer"); ReservedSpace = 1+NumDests; - NumOperands = 1; - OperandList = allocHungoffUses(ReservedSpace); - - OperandList[0] = Address; + setNumHungOffUseOperands(1); + allocHungoffUses(ReservedSpace); + + Op<0>() = Address; } @@ -3549,12 +3381,7 @@ void IndirectBrInst::growOperands() { unsigned NumOps = e*2; ReservedSpace = NumOps; - Use *NewOps = allocHungoffUses(NumOps); - Use *OldOps = OperandList; - for (unsigned i = 0; i != e; ++i) - NewOps[i] = OldOps[i]; - OperandList = NewOps; - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace); } IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases, @@ -3572,29 +3399,26 @@ IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases, } IndirectBrInst::IndirectBrInst(const IndirectBrInst &IBI) - : TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr, - allocHungoffUses(IBI.getNumOperands()), - IBI.getNumOperands()) { - Use *OL = OperandList, *InOL = IBI.OperandList; + : TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr, + nullptr, IBI.getNumOperands()) { + allocHungoffUses(IBI.getNumOperands()); + Use *OL = getOperandList(); + const Use *InOL = IBI.getOperandList(); for (unsigned i = 0, E = IBI.getNumOperands(); i != E; ++i) OL[i] = InOL[i]; SubclassOptionalData = IBI.SubclassOptionalData; } -IndirectBrInst::~IndirectBrInst() { - dropHungoffUses(); -} - /// addDestination - Add a destination. /// void IndirectBrInst::addDestination(BasicBlock *DestBB) { - unsigned OpNo = NumOperands; + unsigned OpNo = getNumOperands(); if (OpNo+1 > ReservedSpace) growOperands(); // Get more space! // Initialize some new operands. assert(OpNo < ReservedSpace && "Growing didn't work!"); - NumOperands = OpNo+1; - OperandList[OpNo] = DestBB; + setNumHungOffUseOperands(OpNo+1); + getOperandList()[OpNo] = DestBB; } /// removeDestination - This method removes the specified successor from the @@ -3603,14 +3427,14 @@ void IndirectBrInst::removeDestination(unsigned idx) { assert(idx < getNumOperands()-1 && "Successor index out of range!"); unsigned NumOps = getNumOperands(); - Use *OL = OperandList; + Use *OL = getOperandList(); // Replace this value with the last one. OL[idx+1] = OL[NumOps-1]; // Nuke the last value. OL[NumOps-1].set(nullptr); - NumOperands = NumOps-1; + setNumHungOffUseOperands(NumOps-1); } BasicBlock *IndirectBrInst::getSuccessorV(unsigned idx) const { diff --git a/contrib/llvm/lib/IR/LLVMContext.cpp b/contrib/llvm/lib/IR/LLVMContext.cpp index b6d95c4..6d799e4 100644 --- a/contrib/llvm/lib/IR/LLVMContext.cpp +++ b/contrib/llvm/lib/IR/LLVMContext.cpp @@ -88,11 +88,22 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { "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; + + // Create the 'dereferenceable' metadata kind. + unsigned DereferenceableID = getMDKindID("dereferenceable"); + assert(DereferenceableID == MD_dereferenceable && + "dereferenceable kind id drifted"); + (void)DereferenceableID; + + // Create the 'dereferenceable_or_null' metadata kind. + unsigned DereferenceableOrNullID = getMDKindID("dereferenceable_or_null"); + assert(DereferenceableOrNullID == MD_dereferenceable_or_null && + "dereferenceable_or_null kind id drifted"); + (void)DereferenceableOrNullID; } LLVMContext::~LLVMContext() { delete pImpl; } @@ -188,6 +199,20 @@ static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { return true; } +static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { + switch (Severity) { + case DS_Error: + return "error"; + case DS_Warning: + return "warning"; + case DS_Remark: + return "remark"; + case DS_Note: + return "note"; + } + llvm_unreachable("Unknown DiagnosticSeverity"); +} + void LLVMContext::diagnose(const DiagnosticInfo &DI) { // If there is a report handler, use it. if (pImpl->DiagnosticHandler) { @@ -200,25 +225,12 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) { return; // Otherwise, print the message with a prefix based on the severity. - std::string MsgStorage; - raw_string_ostream Stream(MsgStorage); - DiagnosticPrinterRawOStream DP(Stream); + DiagnosticPrinterRawOStream DP(errs()); + errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; DI.print(DP); - Stream.flush(); - switch (DI.getSeverity()) { - case DS_Error: - errs() << "error: " << MsgStorage << "\n"; + errs() << "\n"; + if (DI.getSeverity() == DS_Error) exit(1); - case DS_Warning: - errs() << "warning: " << MsgStorage << "\n"; - break; - case DS_Remark: - errs() << "remark: " << MsgStorage << "\n"; - break; - case DS_Note: - errs() << "note: " << MsgStorage << "\n"; - break; - } } void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) { @@ -229,15 +241,12 @@ void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) { // Metadata Kind Uniquing //===----------------------------------------------------------------------===// -/// getMDKindID - Return a unique non-zero ID for the specified metadata kind. +/// Return a unique non-zero ID for the specified metadata kind. unsigned LLVMContext::getMDKindID(StringRef Name) const { - assert(!std::isdigit(Name.front()) && - "Named metadata may not start with a digit"); - // If this is new, assign it its ID. - return pImpl->CustomMDKindNames.insert(std::make_pair( - Name, - pImpl->CustomMDKindNames.size())) + return pImpl->CustomMDKindNames.insert( + std::make_pair( + Name, pImpl->CustomMDKindNames.size())) .first->second; } diff --git a/contrib/llvm/lib/IR/LLVMContextImpl.cpp b/contrib/llvm/lib/IR/LLVMContextImpl.cpp index 01a0e6c..d3d2fcd 100644 --- a/contrib/llvm/lib/IR/LLVMContextImpl.cpp +++ b/contrib/llvm/lib/IR/LLVMContextImpl.cpp @@ -35,7 +35,8 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) Int8Ty(C, 8), Int16Ty(C, 16), Int32Ty(C, 32), - Int64Ty(C, 64) { + Int64Ty(C, 64), + Int128Ty(C, 128) { InlineAsmDiagHandler = nullptr; InlineAsmDiagContext = nullptr; DiagnosticHandler = nullptr; @@ -64,7 +65,7 @@ struct DropFirst { P.first->dropAllReferences(); } }; -} +} // namespace LLVMContextImpl::~LLVMContextImpl() { // NOTE: We need to delete the contents of OwnedModules, but Module's dtor @@ -77,10 +78,10 @@ LLVMContextImpl::~LLVMContextImpl() { // unnecessary RAUW when nodes are still unresolved. for (auto *I : DistinctMDNodes) I->dropAllReferences(); - for (auto *I : MDTuples) - I->dropAllReferences(); - for (auto *I : MDLocations) +#define HANDLE_MDNODE_LEAF(CLASS) \ + for (auto *I : CLASS##s) \ I->dropAllReferences(); +#include "llvm/IR/Metadata.def" // Also drop references that come from the Value bridges. for (auto &Pair : ValuesAsMetadata) @@ -89,15 +90,14 @@ LLVMContextImpl::~LLVMContextImpl() { Pair.second->dropUse(); // Destroy MDNodes. - for (UniquableMDNode *I : DistinctMDNodes) + for (MDNode *I : DistinctMDNodes) I->deleteAsSubclass(); - for (MDTuple *I : MDTuples) - delete I; - for (MDLocation *I : MDLocations) +#define HANDLE_MDNODE_LEAF(CLASS) \ + for (CLASS *I : CLASS##s) \ delete I; +#include "llvm/IR/Metadata.def" - // Free the constants. This is important to do here to ensure that they are - // freed before the LeakDetector is torn down. + // Free the constants. std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(), DropFirst()); std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(), @@ -162,6 +162,62 @@ LLVMContextImpl::~LLVMContextImpl() { MDStringCache.clear(); } +void LLVMContextImpl::dropTriviallyDeadConstantArrays() { + bool Changed; + do { + Changed = false; + + for (auto I = ArrayConstants.map_begin(), E = ArrayConstants.map_end(); + I != E; ) { + auto *C = I->first; + I++; + if (C->use_empty()) { + Changed = true; + C->destroyConstant(); + } + } + + } while (Changed); +} + +void Module::dropTriviallyDeadConstantArrays() { + Context.pImpl->dropTriviallyDeadConstantArrays(); +} + +namespace llvm { +/// \brief Make MDOperand transparent for hashing. +/// +/// This overload of an implementation detail of the hashing library makes +/// MDOperand hash to the same value as a \a Metadata pointer. +/// +/// Note that overloading \a hash_value() as follows: +/// +/// \code +/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); } +/// \endcode +/// +/// does not cause MDOperand to be transparent. In particular, a bare pointer +/// doesn't get hashed before it's combined, whereas \a MDOperand would. +static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); } +} // namespace llvm + +unsigned MDNodeOpsKey::calculateHash(MDNode *N, unsigned Offset) { + unsigned Hash = hash_combine_range(N->op_begin() + Offset, N->op_end()); +#ifndef NDEBUG + { + SmallVector<Metadata *, 8> MDs(N->op_begin() + Offset, N->op_end()); + unsigned RawHash = calculateHash(MDs); + assert(Hash == RawHash && + "Expected hash of MDOperand to equal hash of Metadata*"); + } +#endif + return Hash; +} + +unsigned MDNodeOpsKey::calculateHash(ArrayRef<Metadata *> Ops) { + return hash_combine_range(Ops.begin(), Ops.end()); +} + // ConstantsContext anchors void UnaryConstantExpr::anchor() { } @@ -182,3 +238,4 @@ void InsertValueConstantExpr::anchor() { } void GetElementPtrConstantExpr::anchor() { } void CompareConstantExpr::anchor() { } + diff --git a/contrib/llvm/lib/IR/LLVMContextImpl.h b/contrib/llvm/lib/IR/LLVMContextImpl.h index 6ebc567..41a898b 100644 --- a/contrib/llvm/lib/IR/LLVMContextImpl.h +++ b/contrib/llvm/lib/IR/LLVMContextImpl.h @@ -17,7 +17,6 @@ #include "AttributeImpl.h" #include "ConstantsContext.h" -#include "LeaksContext.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" @@ -28,6 +27,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -41,6 +41,7 @@ class ConstantFP; class DiagnosticInfoOptimizationRemark; class DiagnosticInfoOptimizationRemarkMissed; class DiagnosticInfoOptimizationRemarkAnalysis; +class GCStrategy; class LLVMContext; class Type; class Value; @@ -166,97 +167,731 @@ struct FunctionTypeKeyInfo { } }; +/// \brief Structure for hashing arbitrary MDNode operands. +class MDNodeOpsKey { + ArrayRef<Metadata *> RawOps; + ArrayRef<MDOperand> Ops; + + unsigned Hash; + +protected: + MDNodeOpsKey(ArrayRef<Metadata *> Ops) + : RawOps(Ops), Hash(calculateHash(Ops)) {} + + template <class NodeTy> + MDNodeOpsKey(const NodeTy *N, unsigned Offset = 0) + : Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {} + + template <class NodeTy> + bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const { + if (getHash() != RHS->getHash()) + return false; + + assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?"); + return RawOps.empty() ? compareOps(Ops, RHS, Offset) + : compareOps(RawOps, RHS, Offset); + } + + static unsigned calculateHash(MDNode *N, unsigned Offset = 0); + +private: + template <class T> + static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) { + if (Ops.size() != RHS->getNumOperands() - Offset) + return false; + return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset); + } + + static unsigned calculateHash(ArrayRef<Metadata *> Ops); + +public: + unsigned getHash() const { return Hash; } +}; + +template <class NodeTy> struct MDNodeKeyImpl; +template <class NodeTy> struct MDNodeInfo; + /// \brief DenseMapInfo for MDTuple. /// /// Note that we don't need the is-function-local bit, since that's implicit in /// the operands. -struct MDTupleInfo { - struct KeyTy { - ArrayRef<Metadata *> RawOps; - ArrayRef<MDOperand> Ops; - unsigned Hash; +template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey { + MDNodeKeyImpl(ArrayRef<Metadata *> Ops) : MDNodeOpsKey(Ops) {} + MDNodeKeyImpl(const MDTuple *N) : MDNodeOpsKey(N) {} - KeyTy(ArrayRef<Metadata *> Ops) - : RawOps(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {} + bool isKeyOf(const MDTuple *RHS) const { return compareOps(RHS); } - KeyTy(MDTuple *N) - : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {} + unsigned getHashValue() const { return getHash(); } - bool operator==(const MDTuple *RHS) const { - if (RHS == getEmptyKey() || RHS == getTombstoneKey()) - return false; - if (Hash != RHS->getHash()) - return false; - assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?"); - return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS); - } - template <class T> - static bool compareOps(ArrayRef<T> Ops, const MDTuple *RHS) { - if (Ops.size() != RHS->getNumOperands()) - return false; - return std::equal(Ops.begin(), Ops.end(), RHS->op_begin()); - } - }; - static inline MDTuple *getEmptyKey() { - return DenseMapInfo<MDTuple *>::getEmptyKey(); + static unsigned calculateHash(MDTuple *N) { + return MDNodeOpsKey::calculateHash(N); } - static inline MDTuple *getTombstoneKey() { - return DenseMapInfo<MDTuple *>::getTombstoneKey(); +}; + +/// \brief DenseMapInfo for DILocation. +template <> struct MDNodeKeyImpl<DILocation> { + unsigned Line; + unsigned Column; + Metadata *Scope; + Metadata *InlinedAt; + + MDNodeKeyImpl(unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt) + : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt) {} + + MDNodeKeyImpl(const DILocation *L) + : Line(L->getLine()), Column(L->getColumn()), Scope(L->getRawScope()), + InlinedAt(L->getRawInlinedAt()) {} + + bool isKeyOf(const DILocation *RHS) const { + return Line == RHS->getLine() && Column == RHS->getColumn() && + Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt(); } - static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; } - static unsigned getHashValue(const MDTuple *U) { - return U->getHash(); + unsigned getHashValue() const { + return hash_combine(Line, Column, Scope, InlinedAt); } - static bool isEqual(const KeyTy &LHS, const MDTuple *RHS) { - return LHS == RHS; +}; + +/// \brief DenseMapInfo for GenericDINode. +template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey { + unsigned Tag; + StringRef Header; + MDNodeKeyImpl(unsigned Tag, StringRef Header, ArrayRef<Metadata *> DwarfOps) + : MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {} + MDNodeKeyImpl(const GenericDINode *N) + : MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getHeader()) {} + + bool isKeyOf(const GenericDINode *RHS) const { + return Tag == RHS->getTag() && Header == RHS->getHeader() && + compareOps(RHS, 1); } - static bool isEqual(const MDTuple *LHS, const MDTuple *RHS) { - return LHS == RHS; + + unsigned getHashValue() const { return hash_combine(getHash(), Tag, Header); } + + static unsigned calculateHash(GenericDINode *N) { + return MDNodeOpsKey::calculateHash(N, 1); } }; -/// \brief DenseMapInfo for MDLocation. -struct MDLocationInfo { - struct KeyTy { - unsigned Line; - unsigned Column; - Metadata *Scope; - Metadata *InlinedAt; +template <> struct MDNodeKeyImpl<DISubrange> { + int64_t Count; + int64_t LowerBound; - KeyTy(unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt) - : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt) {} + MDNodeKeyImpl(int64_t Count, int64_t LowerBound) + : Count(Count), LowerBound(LowerBound) {} + MDNodeKeyImpl(const DISubrange *N) + : Count(N->getCount()), LowerBound(N->getLowerBound()) {} - KeyTy(const MDLocation *L) - : Line(L->getLine()), Column(L->getColumn()), Scope(L->getScope()), - InlinedAt(L->getInlinedAt()) {} + bool isKeyOf(const DISubrange *RHS) const { + return Count == RHS->getCount() && LowerBound == RHS->getLowerBound(); + } + unsigned getHashValue() const { return hash_combine(Count, LowerBound); } +}; - bool operator==(const MDLocation *RHS) const { - if (RHS == getEmptyKey() || RHS == getTombstoneKey()) - return false; - return Line == RHS->getLine() && Column == RHS->getColumn() && - Scope == RHS->getScope() && InlinedAt == RHS->getInlinedAt(); - } - }; - static inline MDLocation *getEmptyKey() { - return DenseMapInfo<MDLocation *>::getEmptyKey(); +template <> struct MDNodeKeyImpl<DIEnumerator> { + int64_t Value; + StringRef Name; + + MDNodeKeyImpl(int64_t Value, StringRef Name) : Value(Value), Name(Name) {} + MDNodeKeyImpl(const DIEnumerator *N) + : Value(N->getValue()), Name(N->getName()) {} + + bool isKeyOf(const DIEnumerator *RHS) const { + return Value == RHS->getValue() && Name == RHS->getName(); } - static inline MDLocation *getTombstoneKey() { - return DenseMapInfo<MDLocation *>::getTombstoneKey(); + unsigned getHashValue() const { return hash_combine(Value, Name); } +}; + +template <> struct MDNodeKeyImpl<DIBasicType> { + unsigned Tag; + StringRef Name; + uint64_t SizeInBits; + uint64_t AlignInBits; + unsigned Encoding; + + MDNodeKeyImpl(unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding) + : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits), + Encoding(Encoding) {} + MDNodeKeyImpl(const DIBasicType *N) + : Tag(N->getTag()), Name(N->getName()), SizeInBits(N->getSizeInBits()), + AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()) {} + + bool isKeyOf(const DIBasicType *RHS) const { + return Tag == RHS->getTag() && Name == RHS->getName() && + SizeInBits == RHS->getSizeInBits() && + AlignInBits == RHS->getAlignInBits() && + Encoding == RHS->getEncoding(); } - static unsigned getHashValue(const KeyTy &Key) { - return hash_combine(Key.Line, Key.Column, Key.Scope, Key.InlinedAt); + unsigned getHashValue() const { + return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding); } - static unsigned getHashValue(const MDLocation *U) { - return getHashValue(KeyTy(U)); +}; + +template <> struct MDNodeKeyImpl<DIDerivedType> { + unsigned Tag; + StringRef Name; + Metadata *File; + unsigned Line; + Metadata *Scope; + Metadata *BaseType; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + unsigned Flags; + Metadata *ExtraData; + + MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData) + : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), + BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits), Flags(Flags), ExtraData(ExtraData) {} + MDNodeKeyImpl(const DIDerivedType *N) + : Tag(N->getTag()), Name(N->getName()), File(N->getRawFile()), + Line(N->getLine()), Scope(N->getRawScope()), + BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), + AlignInBits(N->getAlignInBits()), OffsetInBits(N->getOffsetInBits()), + Flags(N->getFlags()), ExtraData(N->getRawExtraData()) {} + + bool isKeyOf(const DIDerivedType *RHS) const { + return Tag == RHS->getTag() && Name == RHS->getName() && + File == RHS->getRawFile() && Line == RHS->getLine() && + Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && + SizeInBits == RHS->getSizeInBits() && + AlignInBits == RHS->getAlignInBits() && + OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && + ExtraData == RHS->getRawExtraData(); } - static bool isEqual(const KeyTy &LHS, const MDLocation *RHS) { - return LHS == RHS; + unsigned getHashValue() const { + return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData); + } +}; + +template <> struct MDNodeKeyImpl<DICompositeType> { + unsigned Tag; + StringRef Name; + Metadata *File; + unsigned Line; + Metadata *Scope; + Metadata *BaseType; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + unsigned Flags; + Metadata *Elements; + unsigned RuntimeLang; + Metadata *VTableHolder; + Metadata *TemplateParams; + StringRef Identifier; + + MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + StringRef Identifier) + : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), + BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits), Flags(Flags), Elements(Elements), + RuntimeLang(RuntimeLang), VTableHolder(VTableHolder), + TemplateParams(TemplateParams), Identifier(Identifier) {} + MDNodeKeyImpl(const DICompositeType *N) + : Tag(N->getTag()), Name(N->getName()), File(N->getRawFile()), + Line(N->getLine()), Scope(N->getRawScope()), + BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), + AlignInBits(N->getAlignInBits()), OffsetInBits(N->getOffsetInBits()), + Flags(N->getFlags()), Elements(N->getRawElements()), + RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()), + TemplateParams(N->getRawTemplateParams()), + Identifier(N->getIdentifier()) {} + + bool isKeyOf(const DICompositeType *RHS) const { + return Tag == RHS->getTag() && Name == RHS->getName() && + File == RHS->getRawFile() && Line == RHS->getLine() && + Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && + SizeInBits == RHS->getSizeInBits() && + AlignInBits == RHS->getAlignInBits() && + OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && + Elements == RHS->getRawElements() && + RuntimeLang == RHS->getRuntimeLang() && + VTableHolder == RHS->getRawVTableHolder() && + TemplateParams == RHS->getRawTemplateParams() && + Identifier == RHS->getIdentifier(); + } + unsigned getHashValue() const { + return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier); + } +}; + +template <> struct MDNodeKeyImpl<DISubroutineType> { + unsigned Flags; + Metadata *TypeArray; + + MDNodeKeyImpl(int64_t Flags, Metadata *TypeArray) + : Flags(Flags), TypeArray(TypeArray) {} + MDNodeKeyImpl(const DISubroutineType *N) + : Flags(N->getFlags()), TypeArray(N->getRawTypeArray()) {} + + bool isKeyOf(const DISubroutineType *RHS) const { + return Flags == RHS->getFlags() && TypeArray == RHS->getRawTypeArray(); + } + unsigned getHashValue() const { return hash_combine(Flags, TypeArray); } +}; + +template <> struct MDNodeKeyImpl<DIFile> { + StringRef Filename; + StringRef Directory; + + MDNodeKeyImpl(StringRef Filename, StringRef Directory) + : Filename(Filename), Directory(Directory) {} + MDNodeKeyImpl(const DIFile *N) + : Filename(N->getFilename()), Directory(N->getDirectory()) {} + + bool isKeyOf(const DIFile *RHS) const { + return Filename == RHS->getFilename() && Directory == RHS->getDirectory(); + } + unsigned getHashValue() const { return hash_combine(Filename, Directory); } +}; + +template <> struct MDNodeKeyImpl<DICompileUnit> { + unsigned SourceLanguage; + Metadata *File; + StringRef Producer; + bool IsOptimized; + StringRef Flags; + unsigned RuntimeVersion; + StringRef SplitDebugFilename; + unsigned EmissionKind; + Metadata *EnumTypes; + Metadata *RetainedTypes; + Metadata *Subprograms; + Metadata *GlobalVariables; + Metadata *ImportedEntities; + uint64_t DWOId; + + MDNodeKeyImpl(unsigned SourceLanguage, Metadata *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, uint64_t DWOId) + : SourceLanguage(SourceLanguage), File(File), Producer(Producer), + IsOptimized(IsOptimized), Flags(Flags), RuntimeVersion(RuntimeVersion), + SplitDebugFilename(SplitDebugFilename), EmissionKind(EmissionKind), + EnumTypes(EnumTypes), RetainedTypes(RetainedTypes), + Subprograms(Subprograms), GlobalVariables(GlobalVariables), + ImportedEntities(ImportedEntities), DWOId(DWOId) {} + MDNodeKeyImpl(const DICompileUnit *N) + : SourceLanguage(N->getSourceLanguage()), File(N->getRawFile()), + Producer(N->getProducer()), IsOptimized(N->isOptimized()), + Flags(N->getFlags()), RuntimeVersion(N->getRuntimeVersion()), + SplitDebugFilename(N->getSplitDebugFilename()), + EmissionKind(N->getEmissionKind()), EnumTypes(N->getRawEnumTypes()), + RetainedTypes(N->getRawRetainedTypes()), + Subprograms(N->getRawSubprograms()), + GlobalVariables(N->getRawGlobalVariables()), + ImportedEntities(N->getRawImportedEntities()), DWOId(N->getDWOId()) {} + + bool isKeyOf(const DICompileUnit *RHS) const { + return SourceLanguage == RHS->getSourceLanguage() && + File == RHS->getRawFile() && Producer == RHS->getProducer() && + IsOptimized == RHS->isOptimized() && Flags == RHS->getFlags() && + RuntimeVersion == RHS->getRuntimeVersion() && + SplitDebugFilename == RHS->getSplitDebugFilename() && + EmissionKind == RHS->getEmissionKind() && + EnumTypes == RHS->getRawEnumTypes() && + RetainedTypes == RHS->getRawRetainedTypes() && + Subprograms == RHS->getRawSubprograms() && + GlobalVariables == RHS->getRawGlobalVariables() && + ImportedEntities == RHS->getRawImportedEntities() && + DWOId == RHS->getDWOId(); + } + unsigned getHashValue() const { + return hash_combine(SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities, DWOId); + } +}; + +template <> struct MDNodeKeyImpl<DISubprogram> { + Metadata *Scope; + StringRef Name; + StringRef LinkageName; + Metadata *File; + unsigned Line; + Metadata *Type; + bool IsLocalToUnit; + bool IsDefinition; + unsigned ScopeLine; + Metadata *ContainingType; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsOptimized; + Metadata *Function; + Metadata *TemplateParams; + Metadata *Declaration; + Metadata *Variables; + + MDNodeKeyImpl(Metadata *Scope, StringRef Name, StringRef LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function, Metadata *TemplateParams, + Metadata *Declaration, Metadata *Variables) + : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), + Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), ScopeLine(ScopeLine), + ContainingType(ContainingType), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsOptimized(IsOptimized), + Function(Function), TemplateParams(TemplateParams), + Declaration(Declaration), Variables(Variables) {} + MDNodeKeyImpl(const DISubprogram *N) + : Scope(N->getRawScope()), Name(N->getName()), + LinkageName(N->getLinkageName()), File(N->getRawFile()), + Line(N->getLine()), Type(N->getRawType()), + IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), + ScopeLine(N->getScopeLine()), ContainingType(N->getRawContainingType()), + Virtuality(N->getVirtuality()), VirtualIndex(N->getVirtualIndex()), + Flags(N->getFlags()), IsOptimized(N->isOptimized()), + Function(N->getRawFunction()), + TemplateParams(N->getRawTemplateParams()), + Declaration(N->getRawDeclaration()), Variables(N->getRawVariables()) {} + + bool isKeyOf(const DISubprogram *RHS) const { + return Scope == RHS->getRawScope() && Name == RHS->getName() && + LinkageName == RHS->getLinkageName() && File == RHS->getRawFile() && + Line == RHS->getLine() && Type == RHS->getRawType() && + IsLocalToUnit == RHS->isLocalToUnit() && + IsDefinition == RHS->isDefinition() && + ScopeLine == RHS->getScopeLine() && + ContainingType == RHS->getRawContainingType() && + Virtuality == RHS->getVirtuality() && + VirtualIndex == RHS->getVirtualIndex() && Flags == RHS->getFlags() && + IsOptimized == RHS->isOptimized() && + Function == RHS->getRawFunction() && + TemplateParams == RHS->getRawTemplateParams() && + Declaration == RHS->getRawDeclaration() && + Variables == RHS->getRawVariables(); + } + unsigned getHashValue() const { + return hash_combine(Scope, Name, LinkageName, File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables); + } +}; + +template <> struct MDNodeKeyImpl<DILexicalBlock> { + Metadata *Scope; + Metadata *File; + unsigned Line; + unsigned Column; + + MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column) + : Scope(Scope), File(File), Line(Line), Column(Column) {} + MDNodeKeyImpl(const DILexicalBlock *N) + : Scope(N->getRawScope()), File(N->getRawFile()), Line(N->getLine()), + Column(N->getColumn()) {} + + bool isKeyOf(const DILexicalBlock *RHS) const { + return Scope == RHS->getRawScope() && File == RHS->getRawFile() && + Line == RHS->getLine() && Column == RHS->getColumn(); + } + unsigned getHashValue() const { + return hash_combine(Scope, File, Line, Column); + } +}; + +template <> struct MDNodeKeyImpl<DILexicalBlockFile> { + Metadata *Scope; + Metadata *File; + unsigned Discriminator; + + MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator) + : Scope(Scope), File(File), Discriminator(Discriminator) {} + MDNodeKeyImpl(const DILexicalBlockFile *N) + : Scope(N->getRawScope()), File(N->getRawFile()), + Discriminator(N->getDiscriminator()) {} + + bool isKeyOf(const DILexicalBlockFile *RHS) const { + return Scope == RHS->getRawScope() && File == RHS->getRawFile() && + Discriminator == RHS->getDiscriminator(); + } + unsigned getHashValue() const { + return hash_combine(Scope, File, Discriminator); + } +}; + +template <> struct MDNodeKeyImpl<DINamespace> { + Metadata *Scope; + Metadata *File; + StringRef Name; + unsigned Line; + + MDNodeKeyImpl(Metadata *Scope, Metadata *File, StringRef Name, unsigned Line) + : Scope(Scope), File(File), Name(Name), Line(Line) {} + MDNodeKeyImpl(const DINamespace *N) + : Scope(N->getRawScope()), File(N->getRawFile()), Name(N->getName()), + Line(N->getLine()) {} + + bool isKeyOf(const DINamespace *RHS) const { + return Scope == RHS->getRawScope() && File == RHS->getRawFile() && + Name == RHS->getName() && Line == RHS->getLine(); + } + unsigned getHashValue() const { + return hash_combine(Scope, File, Name, Line); + } +}; + +template <> struct MDNodeKeyImpl<DITemplateTypeParameter> { + StringRef Name; + Metadata *Type; + + MDNodeKeyImpl(StringRef Name, Metadata *Type) : Name(Name), Type(Type) {} + MDNodeKeyImpl(const DITemplateTypeParameter *N) + : Name(N->getName()), Type(N->getRawType()) {} + + bool isKeyOf(const DITemplateTypeParameter *RHS) const { + return Name == RHS->getName() && Type == RHS->getRawType(); } - static bool isEqual(const MDLocation *LHS, const MDLocation *RHS) { + unsigned getHashValue() const { return hash_combine(Name, Type); } +}; + +template <> struct MDNodeKeyImpl<DITemplateValueParameter> { + unsigned Tag; + StringRef Name; + Metadata *Type; + Metadata *Value; + + MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *Type, Metadata *Value) + : Tag(Tag), Name(Name), Type(Type), Value(Value) {} + MDNodeKeyImpl(const DITemplateValueParameter *N) + : Tag(N->getTag()), Name(N->getName()), Type(N->getRawType()), + Value(N->getValue()) {} + + bool isKeyOf(const DITemplateValueParameter *RHS) const { + return Tag == RHS->getTag() && Name == RHS->getName() && + Type == RHS->getRawType() && Value == RHS->getValue(); + } + unsigned getHashValue() const { return hash_combine(Tag, Name, Type, Value); } +}; + +template <> struct MDNodeKeyImpl<DIGlobalVariable> { + Metadata *Scope; + StringRef Name; + StringRef LinkageName; + Metadata *File; + unsigned Line; + Metadata *Type; + bool IsLocalToUnit; + bool IsDefinition; + Metadata *Variable; + Metadata *StaticDataMemberDeclaration; + + MDNodeKeyImpl(Metadata *Scope, StringRef Name, StringRef LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration) + : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), + Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), Variable(Variable), + StaticDataMemberDeclaration(StaticDataMemberDeclaration) {} + MDNodeKeyImpl(const DIGlobalVariable *N) + : Scope(N->getRawScope()), Name(N->getName()), + LinkageName(N->getLinkageName()), File(N->getRawFile()), + Line(N->getLine()), Type(N->getRawType()), + IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), + Variable(N->getRawVariable()), + StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()) {} + + bool isKeyOf(const DIGlobalVariable *RHS) const { + return Scope == RHS->getRawScope() && Name == RHS->getName() && + LinkageName == RHS->getLinkageName() && File == RHS->getRawFile() && + Line == RHS->getLine() && Type == RHS->getRawType() && + IsLocalToUnit == RHS->isLocalToUnit() && + IsDefinition == RHS->isDefinition() && + Variable == RHS->getRawVariable() && + StaticDataMemberDeclaration == + RHS->getRawStaticDataMemberDeclaration(); + } + unsigned getHashValue() const { + return hash_combine(Scope, Name, LinkageName, File, Line, Type, + IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration); + } +}; + +template <> struct MDNodeKeyImpl<DILocalVariable> { + unsigned Tag; + Metadata *Scope; + StringRef Name; + Metadata *File; + unsigned Line; + Metadata *Type; + unsigned Arg; + unsigned Flags; + + MDNodeKeyImpl(unsigned Tag, Metadata *Scope, StringRef Name, Metadata *File, + unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags) + : Tag(Tag), Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), + Arg(Arg), Flags(Flags) {} + MDNodeKeyImpl(const DILocalVariable *N) + : Tag(N->getTag()), Scope(N->getRawScope()), Name(N->getName()), + File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), + Arg(N->getArg()), Flags(N->getFlags()) {} + + bool isKeyOf(const DILocalVariable *RHS) const { + return Tag == RHS->getTag() && Scope == RHS->getRawScope() && + Name == RHS->getName() && File == RHS->getRawFile() && + Line == RHS->getLine() && Type == RHS->getRawType() && + Arg == RHS->getArg() && Flags == RHS->getFlags(); + } + unsigned getHashValue() const { + return hash_combine(Tag, Scope, Name, File, Line, Type, Arg, Flags); + } +}; + +template <> struct MDNodeKeyImpl<DIExpression> { + ArrayRef<uint64_t> Elements; + + MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {} + MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElements()) {} + + bool isKeyOf(const DIExpression *RHS) const { + return Elements == RHS->getElements(); + } + unsigned getHashValue() const { + return hash_combine_range(Elements.begin(), Elements.end()); + } +}; + +template <> struct MDNodeKeyImpl<DIObjCProperty> { + StringRef Name; + Metadata *File; + unsigned Line; + StringRef GetterName; + StringRef SetterName; + unsigned Attributes; + Metadata *Type; + + MDNodeKeyImpl(StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + Metadata *Type) + : Name(Name), File(File), Line(Line), GetterName(GetterName), + SetterName(SetterName), Attributes(Attributes), Type(Type) {} + MDNodeKeyImpl(const DIObjCProperty *N) + : Name(N->getName()), File(N->getRawFile()), Line(N->getLine()), + GetterName(N->getGetterName()), SetterName(N->getSetterName()), + Attributes(N->getAttributes()), Type(N->getRawType()) {} + + bool isKeyOf(const DIObjCProperty *RHS) const { + return Name == RHS->getName() && File == RHS->getRawFile() && + Line == RHS->getLine() && GetterName == RHS->getGetterName() && + SetterName == RHS->getSetterName() && + Attributes == RHS->getAttributes() && Type == RHS->getRawType(); + } + unsigned getHashValue() const { + return hash_combine(Name, File, Line, GetterName, SetterName, Attributes, + Type); + } +}; + +template <> struct MDNodeKeyImpl<DIImportedEntity> { + unsigned Tag; + Metadata *Scope; + Metadata *Entity; + unsigned Line; + StringRef Name; + + MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, unsigned Line, + StringRef Name) + : Tag(Tag), Scope(Scope), Entity(Entity), Line(Line), Name(Name) {} + MDNodeKeyImpl(const DIImportedEntity *N) + : Tag(N->getTag()), Scope(N->getRawScope()), Entity(N->getRawEntity()), + Line(N->getLine()), Name(N->getName()) {} + + bool isKeyOf(const DIImportedEntity *RHS) const { + return Tag == RHS->getTag() && Scope == RHS->getRawScope() && + Entity == RHS->getRawEntity() && Line == RHS->getLine() && + Name == RHS->getName(); + } + unsigned getHashValue() const { + return hash_combine(Tag, Scope, Entity, Line, Name); + } +}; + +/// \brief DenseMapInfo for MDNode subclasses. +template <class NodeTy> struct MDNodeInfo { + typedef MDNodeKeyImpl<NodeTy> KeyTy; + static inline NodeTy *getEmptyKey() { + return DenseMapInfo<NodeTy *>::getEmptyKey(); + } + static inline NodeTy *getTombstoneKey() { + return DenseMapInfo<NodeTy *>::getTombstoneKey(); + } + static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); } + static unsigned getHashValue(const NodeTy *N) { + return KeyTy(N).getHashValue(); + } + static bool isEqual(const KeyTy &LHS, const NodeTy *RHS) { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + return LHS.isKeyOf(RHS); + } + static bool isEqual(const NodeTy *LHS, const NodeTy *RHS) { return LHS == RHS; } }; +#define HANDLE_MDNODE_LEAF(CLASS) typedef MDNodeInfo<CLASS> CLASS##Info; +#include "llvm/IR/Metadata.def" + +/// \brief Map-like storage for metadata attachments. +class MDAttachmentMap { + SmallVector<std::pair<unsigned, TrackingMDNodeRef>, 2> Attachments; + +public: + bool empty() const { return Attachments.empty(); } + size_t size() const { return Attachments.size(); } + + /// \brief Get a particular attachment (if any). + MDNode *lookup(unsigned ID) const; + + /// \brief Set an attachment to a particular node. + /// + /// Set the \c ID attachment to \c MD, replacing the current attachment at \c + /// ID (if anyway). + void set(unsigned ID, MDNode &MD); + + /// \brief Remove an attachment. + /// + /// Remove the attachment at \c ID, if any. + void erase(unsigned ID); + + /// \brief Copy out all the attachments. + /// + /// Copies all the current attachments into \c Result, sorting by attachment + /// ID. This function does \em not clear \c Result. + void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const; + + /// \brief Erase matching attachments. + /// + /// Erases all attachments matching the \c shouldRemove predicate. + template <class PredTy> void remove_if(PredTy shouldRemove) { + Attachments.erase( + std::remove_if(Attachments.begin(), Attachments.end(), shouldRemove), + Attachments.end()); + } +}; + class LLVMContextImpl { public: /// OwnedModules - The set of modules instantiated in this context, and which @@ -287,14 +922,16 @@ public: DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata; DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues; - DenseSet<MDTuple *, MDTupleInfo> MDTuples; - DenseSet<MDLocation *, MDLocationInfo> MDLocations; + DenseMap<const Value*, ValueName*> ValueNames; + +#define HANDLE_MDNODE_LEAF(CLASS) DenseSet<CLASS *, CLASS##Info> CLASS##s; +#include "llvm/IR/Metadata.def" // 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<UniquableMDNode *, 1> DistinctMDNodes; + SmallPtrSet<MDNode *, 1> DistinctMDNodes; DenseMap<Type*, ConstantAggregateZero*> CAZConstants; @@ -321,14 +958,11 @@ public: ConstantInt *TheTrueVal; ConstantInt *TheFalseVal; - - LeakDetectorImpl<Value> LLVMObjects; - LeakDetectorImpl<Metadata> LLVMMDObjects; // Basic type instances. Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy; Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy; - IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty; + IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty; /// TypeAllocator - All dynamically allocated types are allocated from this. @@ -359,23 +993,17 @@ public: /// CustomMDKindNames - Map to hold the metadata string to ID mapping. StringMap<unsigned> CustomMDKindNames; - typedef std::pair<unsigned, TrackingMDNodeRef> MDPairTy; - typedef SmallVector<MDPairTy, 2> MDMapTy; + /// Collection of per-instruction metadata used in this context. + DenseMap<const Instruction *, MDAttachmentMap> InstructionMetadata; + + /// Collection of per-function metadata used in this context. + DenseMap<const Function *, MDAttachmentMap> FunctionMetadata; - /// MetadataStore - Collection of per-instruction metadata used in this - /// context. - DenseMap<const Instruction *, MDMapTy> MetadataStore; - /// DiscriminatorTable - This table maps file:line locations to an /// integer representing the next DWARF path discriminator to assign to /// instructions in different blocks at the same location. DenseMap<std::pair<const char *, unsigned>, unsigned> DiscriminatorTable; - /// IntrinsicIDCache - Cache of intrinsic name (string) to numeric ID mappings - /// requested in this context - typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy; - IntrinsicIDCacheTy IntrinsicIDCache; - /// \brief Mapping from a function to its prefix data, which is stored as the /// operand of an unparented ReturnInst so that the prefix data has a Use. typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy; @@ -389,11 +1017,14 @@ public: int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx); int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx); - + LLVMContextImpl(LLVMContext &C); ~LLVMContextImpl(); + + /// Destroy the ConstantArrays if they are not used. + void dropTriviallyDeadConstantArrays(); }; -} +} // namespace llvm #endif diff --git a/contrib/llvm/lib/IR/LeaksContext.h b/contrib/llvm/lib/IR/LeaksContext.h deleted file mode 100644 index 47704fa..0000000 --- a/contrib/llvm/lib/IR/LeaksContext.h +++ /dev/null @@ -1,103 +0,0 @@ -//===- LeaksContext.h - LeadDetector Implementation ------------*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines various helper methods and classes used by -// LLVMContextImpl for leaks detectors. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_IR_LEAKSCONTEXT_H -#define LLVM_LIB_IR_LEAKSCONTEXT_H - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -template <class T> -struct PrinterTrait { - static void print(const T* P) { errs() << P; } -}; - -template<> -struct PrinterTrait<Value> { - static void print(const Value* P) { errs() << *P; } -}; - -template <> struct PrinterTrait<Metadata> { - static void print(const Metadata *P) { P->print(errs()); } -}; - -template <typename T> -struct LeakDetectorImpl { - explicit LeakDetectorImpl(const char* const name = "") : - Cache(nullptr), Name(name) { } - - void clear() { - Cache = nullptr; - Ts.clear(); - } - - void setName(const char* n) { - Name = n; - } - - // Because the most common usage pattern, by far, is to add a - // garbage object, then remove it immediately, we optimize this - // case. When an object is added, it is not added to the set - // immediately, it is added to the CachedValue Value. If it is - // immediately removed, no set search need be performed. - void addGarbage(const T* o) { - assert(Ts.count(o) == 0 && "Object already in set!"); - if (Cache) { - assert(Cache != o && "Object already in set!"); - Ts.insert(Cache); - } - Cache = o; - } - - void removeGarbage(const T* o) { - if (o == Cache) - Cache = nullptr; // Cache hit - else - Ts.erase(o); - } - - bool hasGarbage(const std::string& Message) { - addGarbage(nullptr); // Flush the Cache - - assert(!Cache && "No value should be cached anymore!"); - - if (!Ts.empty()) { - errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; - for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), - E = Ts.end(); I != E; ++I) { - errs() << '\t'; - PrinterTrait<T>::print(*I); - errs() << '\n'; - } - errs() << '\n'; - - return true; - } - - return false; - } - -private: - SmallPtrSet<const T*, 8> Ts; - const T* Cache; - const char* Name; -}; - -} - -#endif diff --git a/contrib/llvm/lib/IR/LegacyPassManager.cpp b/contrib/llvm/lib/IR/LegacyPassManager.cpp index fa8d50e..881d780 100644 --- a/contrib/llvm/lib/IR/LegacyPassManager.cpp +++ b/contrib/llvm/lib/IR/LegacyPassManager.cpp @@ -88,8 +88,7 @@ PrintAfterAll("print-after-all", static bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI, PassOptionList &PassesToPrint) { - for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) { - const llvm::PassInfo *PassInf = PassesToPrint[i]; + for (auto *PassInf : PassesToPrint) { if (PassInf) if (PassInf->getPassArgument() == PI->getPassArgument()) { return true; @@ -276,8 +275,8 @@ public: void FunctionPassManagerImpl::anchor() {} char FunctionPassManagerImpl::ID = 0; -} // End of legacy namespace -} // End of llvm namespace +} // namespace legacy +} // namespace llvm namespace { //===----------------------------------------------------------------------===// @@ -293,11 +292,9 @@ public: Pass(PT_PassManager, ID), PMDataManager() { } // Delete on the fly managers. - virtual ~MPPassManager() { - for (std::map<Pass *, FunctionPassManagerImpl *>::iterator - I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end(); - I != E; ++I) { - FunctionPassManagerImpl *FPP = I->second; + ~MPPassManager() override { + for (auto &OnTheFlyManager : OnTheFlyManagers) { + FunctionPassManagerImpl *FPP = OnTheFlyManager.second; delete FPP; } } @@ -442,8 +439,8 @@ public: void PassManagerImpl::anchor() {} char PassManagerImpl::ID = 0; -} // End of legacy namespace -} // End of llvm namespace +} // namespace legacy +} // namespace llvm namespace { @@ -466,9 +463,8 @@ public: ~TimingInfo() { // Delete all of the timers, which accumulate their info into the // TimerGroup. - for (DenseMap<Pass*, Timer*>::iterator I = TimingData.begin(), - E = TimingData.end(); I != E; ++I) - delete I->second; + for (auto &I : TimingData) + delete I.second; // TimerGroup is deleted next, printing the report. } @@ -490,7 +486,7 @@ public: } }; -} // End of anon namespace +} // namespace static TimingInfo *TheTimeInfo; @@ -511,9 +507,7 @@ PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) { if (P->getResolver()) PDepth = P->getResolver()->getPMDataManager().getDepth(); - for (SmallVectorImpl<Pass *>::const_iterator I = AnalysisPasses.begin(), - E = AnalysisPasses.end(); I != E; ++I) { - Pass *AP = *I; + for (Pass *AP : AnalysisPasses) { LastUser[AP] = P; if (P == AP) @@ -652,7 +646,7 @@ void PMTopLevelManager::schedulePass(Pass *P) { // are already checked are still available. checkAnalysis = true; } else - // Do not schedule this analysis. Lower level analsyis + // Do not schedule this analysis. Lower level analysis // passes are run on the fly. delete AnalysisPass; } @@ -694,22 +688,19 @@ void PMTopLevelManager::schedulePass(Pass *P) { Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) { // Check pass managers - for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(), - E = PassManagers.end(); I != E; ++I) - if (Pass *P = (*I)->findAnalysisPass(AID, false)) + for (PMDataManager *PassManager : PassManagers) + if (Pass *P = PassManager->findAnalysisPass(AID, false)) return P; // Check other pass managers - for (SmallVectorImpl<PMDataManager *>::iterator - I = IndirectPassManagers.begin(), - E = IndirectPassManagers.end(); I != E; ++I) - if (Pass *P = (*I)->findAnalysisPass(AID, false)) + for (PMDataManager *IndirectPassManager : IndirectPassManagers) + if (Pass *P = IndirectPassManager->findAnalysisPass(AID, false)) return P; // Check the immutable passes. Iterate in reverse order so that we find // the most recently registered passes first. - for (SmallVectorImpl<ImmutablePass *>::reverse_iterator I = - ImmutablePasses.rbegin(), E = ImmutablePasses.rend(); I != E; ++I) { + for (auto I = ImmutablePasses.rbegin(), E = ImmutablePasses.rend(); I != E; + ++I) { AnalysisID PI = (*I)->getPassID(); if (PI == AID) return *I; @@ -719,11 +710,9 @@ Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) { assert(PassInf && "Expected all immutable passes to be initialized"); const std::vector<const PassInfo*> &ImmPI = PassInf->getInterfacesImplemented(); - for (std::vector<const PassInfo*>::const_iterator II = ImmPI.begin(), - EE = ImmPI.end(); II != EE; ++II) { - if ((*II)->getTypeInfo() == AID) + for (const PassInfo *PI : ImmPI) + if (PI->getTypeInfo() == AID) return *I; - } } return nullptr; @@ -755,9 +744,8 @@ void PMTopLevelManager::dumpPasses() const { // (sometimes indirectly), but there's no inheritance relationship // between PMDataManager and Pass, so we have to getAsPass to get // from a PMDataManager* to a Pass*. - for (SmallVectorImpl<PMDataManager *>::const_iterator I = - PassManagers.begin(), E = PassManagers.end(); I != E; ++I) - (*I)->getAsPass()->dumpPassStructure(1); + for (PMDataManager *Manager : PassManagers) + Manager->getAsPass()->dumpPassStructure(1); } void PMTopLevelManager::dumpArguments() const { @@ -1427,11 +1415,8 @@ bool FunctionPassManagerImpl::doInitialization(Module &M) { dumpArguments(); dumpPasses(); - SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses(); - for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(), - E = IPV.end(); I != E; ++I) { - Changed |= (*I)->doInitialization(M); - } + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doInitialization(M); for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) Changed |= getContainedManager(Index)->doInitialization(M); @@ -1445,11 +1430,8 @@ bool FunctionPassManagerImpl::doFinalization(Module &M) { for (int Index = getNumContainedManagers() - 1; Index >= 0; --Index) Changed |= getContainedManager(Index)->doFinalization(M); - SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses(); - for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(), - E = IPV.end(); I != E; ++I) { - Changed |= (*I)->doFinalization(M); - } + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doFinalization(M); return Changed; } @@ -1554,8 +1536,8 @@ bool FPPassManager::runOnFunction(Function &F) { bool FPPassManager::runOnModule(Module &M) { bool Changed = false; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - Changed |= runOnFunction(*I); + for (Function &F : M) + Changed |= runOnFunction(F); return Changed; } @@ -1589,10 +1571,8 @@ MPPassManager::runOnModule(Module &M) { bool Changed = false; // Initialize on-the-fly passes - for (std::map<Pass *, FunctionPassManagerImpl *>::iterator - I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end(); - I != E; ++I) { - FunctionPassManagerImpl *FPP = I->second; + for (auto &OnTheFlyManager : OnTheFlyManagers) { + FunctionPassManagerImpl *FPP = OnTheFlyManager.second; Changed |= FPP->doInitialization(M); } @@ -1633,10 +1613,8 @@ MPPassManager::runOnModule(Module &M) { Changed |= getContainedPass(Index)->doFinalization(M); // Finalize on-the-fly passes - for (std::map<Pass *, FunctionPassManagerImpl *>::iterator - I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end(); - I != E; ++I) { - FunctionPassManagerImpl *FPP = I->second; + for (auto &OnTheFlyManager : OnTheFlyManagers) { + FunctionPassManagerImpl *FPP = OnTheFlyManager.second; // We don't know when is the last time an on-the-fly pass is run, // so we need to releaseMemory / finalize here FPP->releaseMemoryOnTheFly(); @@ -1712,11 +1690,8 @@ bool PassManagerImpl::run(Module &M) { dumpArguments(); dumpPasses(); - SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses(); - for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(), - E = IPV.end(); I != E; ++I) { - Changed |= (*I)->doInitialization(M); - } + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doInitialization(M); initializeAllAnalysisInfo(); for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) { @@ -1724,10 +1699,8 @@ bool PassManagerImpl::run(Module &M) { M.getContext().yield(); } - for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(), - E = IPV.end(); I != E; ++I) { - Changed |= (*I)->doFinalization(M); - } + for (ImmutablePass *ImPass : getImmutablePasses()) + Changed |= ImPass->doFinalization(M); return Changed; } @@ -1823,9 +1796,8 @@ void PMStack::push(PMDataManager *PM) { // Dump content of the pass manager stack. void PMStack::dump() const { - for (std::vector<PMDataManager *>::const_iterator I = S.begin(), - E = S.end(); I != E; ++I) - dbgs() << (*I)->getAsPass()->getPassName() << ' '; + for (PMDataManager *Manager : S) + dbgs() << Manager->getAsPass()->getPassName() << ' '; if (!S.empty()) dbgs() << '\n'; diff --git a/contrib/llvm/lib/IR/MDBuilder.cpp b/contrib/llvm/lib/IR/MDBuilder.cpp index c7fcf7a..b4c5ca7 100644 --- a/contrib/llvm/lib/IR/MDBuilder.cpp +++ b/contrib/llvm/lib/IR/MDBuilder.cpp @@ -53,24 +53,38 @@ MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights) { return MDNode::get(Context, Vals); } +MDNode *MDBuilder::createFunctionEntryCount(uint64_t Count) { + SmallVector<Metadata *, 2> Vals(2); + Vals[0] = createString("function_entry_count"); + + Type *Int64Ty = Type::getInt64Ty(Context); + Vals[1] = createConstant(ConstantInt::get(Int64Ty, Count)); + + return MDNode::get(Context, Vals); +} + MDNode *MDBuilder::createRange(const APInt &Lo, const APInt &Hi) { assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); + + Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); + return createRange(ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi)); +} + +MDNode *MDBuilder::createRange(Constant *Lo, Constant *Hi) { // If the range is everything then it is useless. if (Hi == Lo) return nullptr; // Return the range [Lo, Hi). - Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); - Metadata *Range[2] = {createConstant(ConstantInt::get(Ty, Lo)), - createConstant(ConstantInt::get(Ty, Hi))}; + Metadata *Range[2] = {createConstant(Lo), createConstant(Hi)}; return MDNode::get(Context, Range); } MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) { // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, None); + auto Dummy = MDNode::getTemporary(Context, None); - SmallVector<Metadata *, 3> Args(1, Dummy); + SmallVector<Metadata *, 3> Args(1, Dummy.get()); if (Extra) Args.push_back(Extra); if (!Name.empty()) @@ -82,7 +96,7 @@ MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) { // !1 = metadata !{metadata !0} <- root // Replace the dummy operand with the root node itself and delete the dummy. Root->replaceOperandWith(0, Root); - MDNode::deleteTemporary(Dummy); + // We now have // !1 = metadata !{metadata !1} <- self-referential root return Root; @@ -154,9 +168,16 @@ MDNode *MDBuilder::createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, /// \brief Return metadata for a TBAA tag node with the given /// base type, access type and offset relative to the base type. MDNode *MDBuilder::createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, - uint64_t Offset) { + uint64_t Offset, bool IsConstant) { Type *Int64 = Type::getInt64Ty(Context); - Metadata *Ops[3] = {BaseType, AccessType, - createConstant(ConstantInt::get(Int64, Offset))}; - return MDNode::get(Context, Ops); + if (IsConstant) { + Metadata *Ops[4] = {BaseType, AccessType, + createConstant(ConstantInt::get(Int64, Offset)), + createConstant(ConstantInt::get(Int64, 1))}; + return MDNode::get(Context, Ops); + } else { + Metadata *Ops[3] = {BaseType, AccessType, + createConstant(ConstantInt::get(Int64, Offset))}; + return MDNode::get(Context, Ops); + } } diff --git a/contrib/llvm/lib/IR/Mangler.cpp b/contrib/llvm/lib/IR/Mangler.cpp index 5eeb797..a0e1b25 100644 --- a/contrib/llvm/lib/IR/Mangler.cpp +++ b/contrib/llvm/lib/IR/Mangler.cpp @@ -73,7 +73,7 @@ static bool hasByteCountSuffix(CallingConv::ID CC) { /// 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) { + const DataLayout &DL) { // Calculate arguments size total. unsigned ArgWords = 0; for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); @@ -83,8 +83,8 @@ static void addByteCountSuffix(raw_ostream &OS, const Function *F, if (AI->hasByValOrInAllocaAttr()) Ty = cast<PointerType>(Ty)->getElementType(); // Size should be aligned to pointer size. - unsigned PtrSize = TD.getPointerSize(); - ArgWords += RoundUpToAlignment(TD.getTypeAllocSize(Ty), PtrSize); + unsigned PtrSize = DL.getPointerSize(); + ArgWords += RoundUpToAlignment(DL.getTypeAllocSize(Ty), PtrSize); } OS << '@' << ArgWords; diff --git a/contrib/llvm/lib/IR/Metadata.cpp b/contrib/llvm/lib/IR/Metadata.cpp index 63e5730..1abcf0d 100644 --- a/contrib/llvm/lib/IR/Metadata.cpp +++ b/contrib/llvm/lib/IR/Metadata.cpp @@ -1,4 +1,4 @@ -//===-- Metadata.cpp - Implement Metadata classes -------------------------===// +//===- Metadata.cpp - Implement Metadata classes --------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,7 @@ #include "llvm/IR/Metadata.h" #include "LLVMContextImpl.h" +#include "MetadataImpl.h" #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" @@ -20,6 +21,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/ConstantRange.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -82,8 +84,7 @@ MetadataAsValue *MetadataAsValue::getIfExists(LLVMContext &Context, Metadata *MD) { MD = canonicalizeMetadataForValue(Context, MD); auto &Store = Context.pImpl->MetadataAsValues; - auto I = Store.find(MD); - return I == Store.end() ? nullptr : I->second; + return Store.lookup(MD); } void MetadataAsValue::handleChangedMetadata(Metadata *MD) { @@ -155,7 +156,8 @@ void ReplaceableMetadataImpl::moveRef(void *Ref, void *New, } void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) { - assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Expected non-temp node"); + assert(!(MD && isa<MDNode>(MD) && cast<MDNode>(MD)->isTemporary()) && + "Expected non-temp node"); if (UseMap.empty()) return; @@ -227,8 +229,8 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { if (Owner.is<MetadataAsValue *>()) continue; - // Resolve UniquableMDNodes that point at this. - auto *OwnerMD = dyn_cast<UniquableMDNode>(Owner.get<Metadata *>()); + // Resolve MDNodes that point at this. + auto *OwnerMD = dyn_cast<MDNode>(Owner.get<Metadata *>()); if (!OwnerMD) continue; if (OwnerMD->isResolved()) @@ -254,9 +256,9 @@ ValueAsMetadata *ValueAsMetadata::get(Value *V) { if (!Entry) { assert((isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) && "Expected constant or function-local value"); - assert(!V->NameAndIsUsedByMD.getInt() && + assert(!V->IsUsedByMD && "Expected this to be the only metadata use"); - V->NameAndIsUsedByMD.setInt(true); + V->IsUsedByMD = true; if (auto *C = dyn_cast<Constant>(V)) Entry = new ConstantAsMetadata(C); else @@ -300,15 +302,15 @@ void ValueAsMetadata::handleRAUW(Value *From, Value *To) { auto &Store = Context.pImpl->ValuesAsMetadata; auto I = Store.find(From); if (I == Store.end()) { - assert(!From->NameAndIsUsedByMD.getInt() && + assert(!From->IsUsedByMD && "Expected From not to be used by metadata"); return; } // Remove old entry from the map. - assert(From->NameAndIsUsedByMD.getInt() && + assert(From->IsUsedByMD && "Expected From to be used by metadata"); - From->NameAndIsUsedByMD.setInt(false); + From->IsUsedByMD = false; ValueAsMetadata *MD = I->second; assert(MD && "Expected valid metadata"); assert(MD->getValue() == From && "Expected valid mapping"); @@ -344,9 +346,9 @@ void ValueAsMetadata::handleRAUW(Value *From, Value *To) { } // Update MD in place (and update the map entry). - assert(!To->NameAndIsUsedByMD.getInt() && + assert(!To->IsUsedByMD && "Expected this to be the only metadata use"); - To->NameAndIsUsedByMD.setInt(true); + To->IsUsedByMD = true; MD->V = To; Entry = MD; } @@ -379,33 +381,68 @@ StringRef MDString::getString() const { // MDNode implementation. // +// Assert that the MDNode types will not be unaligned by the objects +// prepended to them. +#define HANDLE_MDNODE_LEAF(CLASS) \ + static_assert( \ + llvm::AlignOf<uint64_t>::Alignment >= llvm::AlignOf<CLASS>::Alignment, \ + "Alignment is insufficient after objects prepended to " #CLASS); +#include "llvm/IR/Metadata.def" + void *MDNode::operator new(size_t Size, unsigned NumOps) { - void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand)); + size_t OpSize = NumOps * sizeof(MDOperand); + // uint64_t is the most aligned type we need support (ensured by static_assert + // above) + OpSize = RoundUpToAlignment(OpSize, llvm::alignOf<uint64_t>()); + void *Ptr = reinterpret_cast<char *>(::operator new(OpSize + Size)) + OpSize; MDOperand *O = static_cast<MDOperand *>(Ptr); - for (MDOperand *E = O + NumOps; O != E; ++O) - (void)new (O) MDOperand; - return O; + for (MDOperand *E = O - NumOps; O != E; --O) + (void)new (O - 1) MDOperand; + return Ptr; } void MDNode::operator delete(void *Mem) { MDNode *N = static_cast<MDNode *>(Mem); + size_t OpSize = N->NumOperands * sizeof(MDOperand); + OpSize = RoundUpToAlignment(OpSize, llvm::alignOf<uint64_t>()); + MDOperand *O = static_cast<MDOperand *>(Mem); for (MDOperand *E = O - N->NumOperands; O != E; --O) (O - 1)->~MDOperand(); - ::operator delete(O); + ::operator delete(reinterpret_cast<char *>(Mem) - OpSize); } -MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs) - : Metadata(ID), Context(Context), NumOperands(MDs.size()), - MDNodeSubclassData(0) { - for (unsigned I = 0, E = MDs.size(); I != E; ++I) - setOperand(I, MDs[I]); +MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2) + : Metadata(ID, Storage), NumOperands(Ops1.size() + Ops2.size()), + NumUnresolved(0), Context(Context) { + unsigned Op = 0; + for (Metadata *MD : Ops1) + setOperand(Op++, MD); + for (Metadata *MD : Ops2) + setOperand(Op++, MD); + + if (isDistinct()) + return; + + if (isUniqued()) + // Check whether any operands are unresolved, requiring re-uniquing. If + // not, don't support RAUW. + if (!countUnresolvedOperands()) + return; + + this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(Context)); } -bool MDNode::isResolved() const { - if (isa<MDNodeFwdDecl>(this)) - return false; - return cast<UniquableMDNode>(this)->isResolved(); +TempMDNode MDNode::clone() const { + switch (getMetadataID()) { + default: + llvm_unreachable("Invalid MDNode subclass"); +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return cast<CLASS>(this)->cloneImpl(); +#include "llvm/IR/Metadata.def" + } } static bool isOperandUnresolved(Metadata *Op) { @@ -414,55 +451,73 @@ static bool isOperandUnresolved(Metadata *Op) { return false; } -UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID, - ArrayRef<Metadata *> Vals, bool AllowRAUW) - : MDNode(C, ID, Vals) { - if (!AllowRAUW) - return; +unsigned MDNode::countUnresolvedOperands() { + assert(NumUnresolved == 0 && "Expected unresolved ops to be uncounted"); + NumUnresolved = std::count_if(op_begin(), op_end(), isOperandUnresolved); + return NumUnresolved; +} + +void MDNode::makeUniqued() { + assert(isTemporary() && "Expected this to be temporary"); + assert(!isResolved() && "Expected this to be unresolved"); - // Check whether any operands are unresolved, requiring re-uniquing. - unsigned NumUnresolved = 0; - for (const auto &Op : operands()) - NumUnresolved += unsigned(isOperandUnresolved(Op)); + // Enable uniquing callbacks. + for (auto &Op : mutable_operands()) + Op.reset(Op.get(), this); - if (!NumUnresolved) - return; + // Make this 'uniqued'. + Storage = Uniqued; + if (!countUnresolvedOperands()) + resolve(); + + assert(isUniqued() && "Expected this to be uniqued"); +} - ReplaceableUses.reset(new ReplaceableMetadataImpl); - SubclassData32 = NumUnresolved; +void MDNode::makeDistinct() { + assert(isTemporary() && "Expected this to be temporary"); + assert(!isResolved() && "Expected this to be unresolved"); + + // Pretend to be uniqued, resolve the node, and then store in distinct table. + Storage = Uniqued; + resolve(); + storeDistinctInContext(); + + assert(isDistinct() && "Expected this to be distinct"); + assert(isResolved() && "Expected this to be resolved"); } -void UniquableMDNode::resolve() { +void MDNode::resolve() { + assert(isUniqued() && "Expected this to be uniqued"); assert(!isResolved() && "Expected this to be unresolved"); // Move the map, so that this immediately looks resolved. - auto Uses = std::move(ReplaceableUses); - SubclassData32 = 0; + auto Uses = Context.takeReplaceableUses(); + NumUnresolved = 0; assert(isResolved() && "Expected this to be resolved"); // Drop RAUW support. Uses->resolveAllUses(); } -void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { - assert(SubclassData32 != 0 && "Expected unresolved operands"); +void MDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { + assert(NumUnresolved != 0 && "Expected unresolved operands"); // Check if an operand was resolved. if (!isOperandUnresolved(Old)) { if (isOperandUnresolved(New)) // An operand was un-resolved! - ++SubclassData32; + ++NumUnresolved; } else if (!isOperandUnresolved(New)) decrementUnresolvedOperandCount(); } -void UniquableMDNode::decrementUnresolvedOperandCount() { - if (!--SubclassData32) +void MDNode::decrementUnresolvedOperandCount() { + if (!--NumUnresolved) // Last unresolved operand has just been resolved. resolve(); } -void UniquableMDNode::resolveCycles() { +void MDNode::resolveCycles() { if (isResolved()) return; @@ -471,62 +526,68 @@ void UniquableMDNode::resolveCycles() { // Resolve all operands. for (const auto &Op : operands()) { - if (!Op) + auto *N = dyn_cast_or_null<MDNode>(Op); + if (!N) continue; - assert(!isa<MDNodeFwdDecl>(Op) && + + assert(!N->isTemporary() && "Expected all forward declarations to be resolved"); - if (auto *N = dyn_cast<UniquableMDNode>(Op)) - if (!N->isResolved()) - N->resolveCycles(); + if (!N->isResolved()) + N->resolveCycles(); } } -void MDTuple::recalculateHash() { - setHash(hash_combine_range(op_begin(), op_end())); -#ifndef NDEBUG - { - SmallVector<Metadata *, 8> MDs(op_begin(), op_end()); - unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end()); - assert(getHash() == RawHash && - "Expected hash of MDOperand to equal hash of Metadata*"); +static bool hasSelfReference(MDNode *N) { + for (Metadata *MD : N->operands()) + if (MD == N) + return true; + return false; +} + +MDNode *MDNode::replaceWithPermanentImpl() { + if (hasSelfReference(this)) + return replaceWithDistinctImpl(); + return replaceWithUniquedImpl(); +} + +MDNode *MDNode::replaceWithUniquedImpl() { + // Try to uniquify in place. + MDNode *UniquedNode = uniquify(); + + if (UniquedNode == this) { + makeUniqued(); + return this; } -#endif + + // Collision, so RAUW instead. + replaceAllUsesWith(UniquedNode); + deleteAsSubclass(); + return UniquedNode; +} + +MDNode *MDNode::replaceWithDistinctImpl() { + makeDistinct(); + return this; +} + +void MDTuple::recalculateHash() { + setHash(MDTupleInfo::KeyTy::calculateHash(this)); } void MDNode::dropAllReferences() { for (unsigned I = 0, E = NumOperands; I != E; ++I) setOperand(I, nullptr); - if (auto *N = dyn_cast<UniquableMDNode>(this)) - if (!N->isResolved()) { - N->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false); - N->ReplaceableUses.reset(); - } -} - -namespace llvm { -/// \brief Make MDOperand transparent for hashing. -/// -/// This overload of an implementation detail of the hashing library makes -/// MDOperand hash to the same value as a \a Metadata pointer. -/// -/// Note that overloading \a hash_value() as follows: -/// -/// \code -/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); } -/// \endcode -/// -/// does not cause MDOperand to be transparent. In particular, a bare pointer -/// doesn't get hashed before it's combined, whereas \a MDOperand would. -static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); } + if (!isResolved()) { + Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false); + (void)Context.takeReplaceableUses(); + } } -void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) { +void MDNode::handleChangedOperand(void *Ref, Metadata *New) { unsigned Op = static_cast<MDOperand *>(Ref) - op_begin(); assert(Op < getNumOperands() && "Expected valid operand"); - if (isStoredDistinctInContext()) { - assert(isResolved() && "Expected distinct node to be resolved"); - + if (!isUniqued()) { // This node is not uniqued. Just set the operand and be done with it. setOperand(Op, New); return; @@ -540,9 +601,9 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) { // Drop uniquing for self-reference cycles. if (New == this) { - storeDistinctInContext(); if (!isResolved()) resolve(); + storeDistinctInContext(); return; } @@ -562,7 +623,7 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) { // dropAllReferences(), but we still need the use-list). for (unsigned O = 0, E = getNumOperands(); O != E; ++O) setOperand(O, nullptr); - ReplaceableUses->replaceAllUsesWith(Uniqued); + Context.getReplaceableUses()->replaceAllUsesWith(Uniqued); deleteAsSubclass(); return; } @@ -571,11 +632,11 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) { storeDistinctInContext(); } -void UniquableMDNode::deleteAsSubclass() { +void MDNode::deleteAsSubclass() { switch (getMetadataID()) { default: - llvm_unreachable("Invalid subclass of UniquableMDNode"); -#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + llvm_unreachable("Invalid subclass of MDNode"); +#define HANDLE_MDNODE_LEAF(CLASS) \ case CLASS##Kind: \ delete cast<CLASS>(this); \ break; @@ -583,167 +644,99 @@ void UniquableMDNode::deleteAsSubclass() { } } -UniquableMDNode *UniquableMDNode::uniquify() { +template <class T, class InfoT> +static T *uniquifyImpl(T *N, DenseSet<T *, InfoT> &Store) { + if (T *U = getUniqued(Store, N)) + return U; + + Store.insert(N); + return N; +} + +template <class NodeTy> struct MDNode::HasCachedHash { + typedef char Yes[1]; + typedef char No[2]; + template <class U, U Val> struct SFINAE {}; + + template <class U> + static Yes &check(SFINAE<void (U::*)(unsigned), &U::setHash> *); + template <class U> static No &check(...); + + static const bool value = sizeof(check<NodeTy>(nullptr)) == sizeof(Yes); +}; + +MDNode *MDNode::uniquify() { + assert(!hasSelfReference(this) && "Cannot uniquify a self-referencing node"); + + // Try to insert into uniquing store. switch (getMetadataID()) { default: - llvm_unreachable("Invalid subclass of UniquableMDNode"); -#define HANDLE_UNIQUABLE_LEAF(CLASS) \ - case CLASS##Kind: \ - return cast<CLASS>(this)->uniquifyImpl(); + llvm_unreachable("Invalid subclass of MDNode"); +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: { \ + CLASS *SubclassThis = cast<CLASS>(this); \ + std::integral_constant<bool, HasCachedHash<CLASS>::value> \ + ShouldRecalculateHash; \ + dispatchRecalculateHash(SubclassThis, ShouldRecalculateHash); \ + return uniquifyImpl(SubclassThis, getContext().pImpl->CLASS##s); \ + } #include "llvm/IR/Metadata.def" } } -void UniquableMDNode::eraseFromStore() { +void MDNode::eraseFromStore() { switch (getMetadataID()) { default: - llvm_unreachable("Invalid subclass of UniquableMDNode"); -#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + llvm_unreachable("Invalid subclass of MDNode"); +#define HANDLE_MDNODE_LEAF(CLASS) \ case CLASS##Kind: \ - cast<CLASS>(this)->eraseFromStoreImpl(); \ + getContext().pImpl->CLASS##s.erase(cast<CLASS>(this)); \ break; #include "llvm/IR/Metadata.def" } } MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs, - bool ShouldCreate) { - MDTupleInfo::KeyTy Key(MDs); - - auto &Store = Context.pImpl->MDTuples; - auto I = Store.find_as(Key); - if (I != Store.end()) - return *I; - if (!ShouldCreate) - return nullptr; - - // Coallocate space for the node and Operands together, then placement new. - auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ true); - N->setHash(Key.Hash); - Store.insert(N); - return N; -} - -MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ false); - N->storeDistinctInContext(); - return N; -} - -MDTuple *MDTuple::uniquifyImpl() { - recalculateHash(); - MDTupleInfo::KeyTy Key(this); - - auto &Store = getContext().pImpl->MDTuples; - auto I = Store.find_as(Key); - if (I == Store.end()) { - Store.insert(this); - return this; + StorageType Storage, bool ShouldCreate) { + unsigned Hash = 0; + if (Storage == Uniqued) { + MDTupleInfo::KeyTy Key(MDs); + if (auto *N = getUniqued(Context.pImpl->MDTuples, Key)) + return N; + if (!ShouldCreate) + return nullptr; + Hash = Key.getHash(); + } else { + assert(ShouldCreate && "Expected non-uniqued nodes to always be created"); } - return *I; -} -void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); } - -MDLocation::MDLocation(LLVMContext &C, unsigned Line, unsigned Column, - ArrayRef<Metadata *> MDs, bool AllowRAUW) - : UniquableMDNode(C, MDLocationKind, MDs, AllowRAUW) { - assert((MDs.size() == 1 || MDs.size() == 2) && - "Expected a scope and optional inlined-at"); - - // Set line and column. - assert(Line < (1u << 24) && "Expected 24-bit line"); - assert(Column < (1u << 8) && "Expected 8-bit column"); - - MDNodeSubclassData = Line; - SubclassData16 = Column; -} - -MDLocation *MDLocation::constructHelper(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool AllowRAUW) { - SmallVector<Metadata *, 2> Ops; - Ops.push_back(Scope); - if (InlinedAt) - Ops.push_back(InlinedAt); - return new (Ops.size()) MDLocation(Context, Line, Column, Ops, AllowRAUW); -} - -static void adjustLine(unsigned &Line) { - // Set to unknown on overflow. Still use 24 bits for now. - if (Line >= (1u << 24)) - Line = 0; -} - -static void adjustColumn(unsigned &Column) { - // Set to unknown on overflow. Still use 8 bits for now. - if (Column >= (1u << 8)) - Column = 0; -} - -MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool ShouldCreate) { - // Fixup line/column. - adjustLine(Line); - adjustColumn(Column); - - MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt); - - auto &Store = Context.pImpl->MDLocations; - auto I = Store.find_as(Key); - if (I != Store.end()) - return *I; - if (!ShouldCreate) - return nullptr; - - auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt, - /* AllowRAUW */ true); - Store.insert(N); - return N; + return storeImpl(new (MDs.size()) MDTuple(Context, Storage, Hash, MDs), + Storage, Context.pImpl->MDTuples); } -MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt) { - // Fixup line/column. - adjustLine(Line); - adjustColumn(Column); - - auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt, - /* AllowRAUW */ false); - N->storeDistinctInContext(); - return N; +void MDNode::deleteTemporary(MDNode *N) { + assert(N->isTemporary() && "Expected temporary node"); + N->replaceAllUsesWith(nullptr); + N->deleteAsSubclass(); } -MDLocation *MDLocation::uniquifyImpl() { - MDLocationInfo::KeyTy Key(this); +void MDNode::storeDistinctInContext() { + assert(isResolved() && "Expected resolved nodes"); + Storage = Distinct; - auto &Store = getContext().pImpl->MDLocations; - auto I = Store.find_as(Key); - if (I == Store.end()) { - Store.insert(this); - return this; + // Reset the hash. + switch (getMetadataID()) { + default: + llvm_unreachable("Invalid subclass of MDNode"); +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: { \ + std::integral_constant<bool, HasCachedHash<CLASS>::value> ShouldResetHash; \ + dispatchResetHash(cast<CLASS>(this), ShouldResetHash); \ + break; \ + } +#include "llvm/IR/Metadata.def" } - return *I; -} - -void MDLocation::eraseFromStoreImpl() { - getContext().pImpl->MDLocations.erase(this); -} - -MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context, - ArrayRef<Metadata *> MDs) { - return MDNodeFwdDecl::get(Context, MDs); -} - -void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); } -void UniquableMDNode::storeDistinctInContext() { - assert(!IsDistinctInContext && "Expected newly distinct metadata"); - IsDistinctInContext = true; - if (auto *T = dyn_cast<MDTuple>(this)) - T->setHash(0); getContext().pImpl->DistinctMDNodes.insert(this); } @@ -751,21 +744,17 @@ void MDNode::replaceOperandWith(unsigned I, Metadata *New) { if (getOperand(I) == New) return; - if (isDistinct()) { + if (!isUniqued()) { setOperand(I, New); return; } - cast<UniquableMDNode>(this)->handleChangedOperand(mutable_begin() + I, New); + handleChangedOperand(mutable_begin() + I, New); } void MDNode::setOperand(unsigned I, Metadata *New) { assert(I < NumOperands); - if (isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this)) - // No need for a callback, this isn't uniqued. - mutable_begin()[I].reset(New, nullptr); - else - mutable_begin()[I].reset(New, this); + mutable_begin()[I].reset(New, isUniqued() ? this : nullptr); } /// \brief Get a node, or a self-reference that looks like it. @@ -794,13 +783,10 @@ MDNode *MDNode::concatenate(MDNode *A, MDNode *B) { if (!B) return A; - SmallVector<Metadata *, 4> MDs(A->getNumOperands() + B->getNumOperands()); - - unsigned j = 0; - for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) - MDs[j++] = A->getOperand(i); - for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i) - MDs[j++] = B->getOperand(i); + SmallVector<Metadata *, 4> MDs; + MDs.reserve(A->getNumOperands() + B->getNumOperands()); + MDs.append(A->op_begin(), A->op_end()); + MDs.append(B->op_begin(), B->op_end()); // FIXME: This preserves long-standing behaviour, but is it really the right // behaviour? Or was that an unintended side-effect of node uniquing? @@ -812,14 +798,9 @@ MDNode *MDNode::intersect(MDNode *A, MDNode *B) { return nullptr; SmallVector<Metadata *, 4> MDs; - for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) { - Metadata *MD = A->getOperand(i); - for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j) - if (MD == B->getOperand(j)) { - MDs.push_back(MD); - break; - } - } + for (Metadata *MD : A->operands()) + if (std::find(B->op_begin(), B->op_end(), MD) != B->op_end()) + MDs.push_back(MD); // FIXME: This preserves long-standing behaviour, but is it really the right // behaviour? Or was that an unintended side-effect of node uniquing? @@ -831,17 +812,9 @@ MDNode *MDNode::getMostGenericAliasScope(MDNode *A, MDNode *B) { return nullptr; SmallVector<Metadata *, 4> MDs(B->op_begin(), B->op_end()); - for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) { - Metadata *MD = A->getOperand(i); - bool insert = true; - for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j) - if (MD == B->getOperand(j)) { - insert = false; - break; - } - if (insert) - MDs.push_back(MD); - } + for (Metadata *MD : A->operands()) + if (std::find(B->op_begin(), B->op_end(), MD) == B->op_end()) + MDs.push_back(MD); // FIXME: This preserves long-standing behaviour, but is it really the right // behaviour? Or was that an unintended side-effect of node uniquing? @@ -1017,6 +990,50 @@ StringRef NamedMDNode::getName() const { //===----------------------------------------------------------------------===// // Instruction Metadata method implementations. // +void MDAttachmentMap::set(unsigned ID, MDNode &MD) { + for (auto &I : Attachments) + if (I.first == ID) { + I.second.reset(&MD); + return; + } + Attachments.emplace_back(std::piecewise_construct, std::make_tuple(ID), + std::make_tuple(&MD)); +} + +void MDAttachmentMap::erase(unsigned ID) { + if (empty()) + return; + + // Common case is one/last value. + if (Attachments.back().first == ID) { + Attachments.pop_back(); + return; + } + + for (auto I = Attachments.begin(), E = std::prev(Attachments.end()); I != E; + ++I) + if (I->first == ID) { + *I = std::move(Attachments.back()); + Attachments.pop_back(); + return; + } +} + +MDNode *MDAttachmentMap::lookup(unsigned ID) const { + for (const auto &I : Attachments) + if (I.first == ID) + return I.second; + return nullptr; +} + +void MDAttachmentMap::getAll( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const { + Result.append(Attachments.begin(), Attachments.end()); + + // Sort the resulting array so it is stable. + if (Result.size() > 1) + array_pod_sort(Result.begin(), Result.end()); +} void Instruction::setMetadata(StringRef Kind, MDNode *Node) { if (!Node && !hasMetadata()) @@ -1039,35 +1056,23 @@ void Instruction::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) { if (!hasMetadataHashEntry()) return; // Nothing to remove! - DenseMap<const Instruction *, LLVMContextImpl::MDMapTy> &MetadataStore = - getContext().pImpl->MetadataStore; + auto &InstructionMetadata = getContext().pImpl->InstructionMetadata; if (KnownSet.empty()) { // Just drop our entry at the store. - MetadataStore.erase(this); + InstructionMetadata.erase(this); setHasMetadataHashEntry(false); return; } - LLVMContextImpl::MDMapTy &Info = MetadataStore[this]; - unsigned I; - unsigned E; - // Walk the array and drop any metadata we don't know. - for (I = 0, E = Info.size(); I != E;) { - if (KnownSet.count(Info[I].first)) { - ++I; - continue; - } - - Info[I] = std::move(Info.back()); - Info.pop_back(); - --E; - } - assert(E == Info.size()); + auto &Info = InstructionMetadata[this]; + Info.remove_if([&KnownSet](const std::pair<unsigned, TrackingMDNodeRef> &I) { + return !KnownSet.count(I.first); + }); - if (E == 0) { + if (Info.empty()) { // Drop our entry at the store. - MetadataStore.erase(this); + InstructionMetadata.erase(this); setHasMetadataHashEntry(false); } } @@ -1081,56 +1086,37 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) { // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) { - DbgLoc = DebugLoc::getFromDILocation(Node); + DbgLoc = DebugLoc(Node); return; } // Handle the case when we're adding/updating metadata on an instruction. if (Node) { - LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this]; + auto &Info = getContext().pImpl->InstructionMetadata[this]; assert(!Info.empty() == hasMetadataHashEntry() && "HasMetadata bit is wonked"); - if (Info.empty()) { + if (Info.empty()) setHasMetadataHashEntry(true); - } else { - // Handle replacement of an existing value. - for (auto &P : Info) - if (P.first == KindID) { - P.second.reset(Node); - return; - } - } - - // No replacement, just add it to the list. - Info.emplace_back(std::piecewise_construct, std::make_tuple(KindID), - std::make_tuple(Node)); + Info.set(KindID, *Node); return; } // Otherwise, we're removing metadata from an instruction. assert((hasMetadataHashEntry() == - (getContext().pImpl->MetadataStore.count(this) > 0)) && + (getContext().pImpl->InstructionMetadata.count(this) > 0)) && "HasMetadata bit out of date!"); if (!hasMetadataHashEntry()) return; // Nothing to remove! - LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this]; + auto &Info = getContext().pImpl->InstructionMetadata[this]; - // Common case is removing the only entry. - if (Info.size() == 1 && Info[0].first == KindID) { - getContext().pImpl->MetadataStore.erase(this); - setHasMetadataHashEntry(false); + // Handle removal of an existing value. + Info.erase(KindID); + + if (!Info.empty()) return; - } - // Handle removal of an existing value. - for (unsigned i = 0, e = Info.size(); i != e; ++i) - if (Info[i].first == KindID) { - Info[i] = std::move(Info.back()); - Info.pop_back(); - assert(!Info.empty() && "Removing last entry should be handled above"); - return; - } - // Otherwise, removing an entry that doesn't exist on the instruction. + getContext().pImpl->InstructionMetadata.erase(this); + setHasMetadataHashEntry(false); } void Instruction::setAAMetadata(const AAMDNodes &N) { @@ -1144,15 +1130,12 @@ MDNode *Instruction::getMetadataImpl(unsigned KindID) const { if (KindID == LLVMContext::MD_dbg) return DbgLoc.getAsMDNode(); - if (!hasMetadataHashEntry()) return nullptr; - - LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this]; + if (!hasMetadataHashEntry()) + return nullptr; + auto &Info = getContext().pImpl->InstructionMetadata[this]; assert(!Info.empty() && "bit out of sync with hash table"); - for (const auto &I : Info) - if (I.first == KindID) - return I.second; - return nullptr; + return Info.lookup(KindID); } void Instruction::getAllMetadataImpl( @@ -1160,50 +1143,111 @@ void Instruction::getAllMetadataImpl( Result.clear(); // Handle 'dbg' as a special case since it is not stored in the hash table. - if (!DbgLoc.isUnknown()) { + if (DbgLoc) { Result.push_back( std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode())); if (!hasMetadataHashEntry()) return; } - + assert(hasMetadataHashEntry() && - getContext().pImpl->MetadataStore.count(this) && + getContext().pImpl->InstructionMetadata.count(this) && "Shouldn't have called this"); - const LLVMContextImpl::MDMapTy &Info = - getContext().pImpl->MetadataStore.find(this)->second; + const auto &Info = getContext().pImpl->InstructionMetadata.find(this)->second; assert(!Info.empty() && "Shouldn't have called this"); - - Result.reserve(Result.size() + Info.size()); - for (auto &I : Info) - Result.push_back(std::make_pair(I.first, cast<MDNode>(I.second.get()))); - - // Sort the resulting array so it is stable. - if (Result.size() > 1) - array_pod_sort(Result.begin(), Result.end()); + Info.getAll(Result); } void Instruction::getAllMetadataOtherThanDebugLocImpl( SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const { Result.clear(); assert(hasMetadataHashEntry() && - getContext().pImpl->MetadataStore.count(this) && + getContext().pImpl->InstructionMetadata.count(this) && "Shouldn't have called this"); - const LLVMContextImpl::MDMapTy &Info = - getContext().pImpl->MetadataStore.find(this)->second; + const auto &Info = getContext().pImpl->InstructionMetadata.find(this)->second; assert(!Info.empty() && "Shouldn't have called this"); - Result.reserve(Result.size() + Info.size()); - for (auto &I : Info) - Result.push_back(std::make_pair(I.first, cast<MDNode>(I.second.get()))); - - // Sort the resulting array so it is stable. - if (Result.size() > 1) - array_pod_sort(Result.begin(), Result.end()); + Info.getAll(Result); } /// clearMetadataHashEntries - Clear all hashtable-based metadata from /// this instruction. void Instruction::clearMetadataHashEntries() { assert(hasMetadataHashEntry() && "Caller should check"); - getContext().pImpl->MetadataStore.erase(this); + getContext().pImpl->InstructionMetadata.erase(this); + setHasMetadataHashEntry(false); +} + +MDNode *Function::getMetadata(unsigned KindID) const { + if (!hasMetadata()) + return nullptr; + return getContext().pImpl->FunctionMetadata[this].lookup(KindID); +} + +MDNode *Function::getMetadata(StringRef Kind) const { + if (!hasMetadata()) + return nullptr; + return getMetadata(getContext().getMDKindID(Kind)); +} + +void Function::setMetadata(unsigned KindID, MDNode *MD) { + if (MD) { + if (!hasMetadata()) + setHasMetadataHashEntry(true); + + getContext().pImpl->FunctionMetadata[this].set(KindID, *MD); + return; + } + + // Nothing to unset. + if (!hasMetadata()) + return; + + auto &Store = getContext().pImpl->FunctionMetadata[this]; + Store.erase(KindID); + if (Store.empty()) + clearMetadata(); +} + +void Function::setMetadata(StringRef Kind, MDNode *MD) { + if (!MD && !hasMetadata()) + return; + setMetadata(getContext().getMDKindID(Kind), MD); +} + +void Function::getAllMetadata( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const { + MDs.clear(); + + if (!hasMetadata()) + return; + + getContext().pImpl->FunctionMetadata[this].getAll(MDs); +} + +void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) { + if (!hasMetadata()) + return; + if (KnownIDs.empty()) { + clearMetadata(); + return; + } + + SmallSet<unsigned, 5> KnownSet; + KnownSet.insert(KnownIDs.begin(), KnownIDs.end()); + + auto &Store = getContext().pImpl->FunctionMetadata[this]; + assert(!Store.empty()); + + Store.remove_if([&KnownSet](const std::pair<unsigned, TrackingMDNodeRef> &I) { + return !KnownSet.count(I.first); + }); + + if (Store.empty()) + clearMetadata(); +} + +void Function::clearMetadata() { + if (!hasMetadata()) + return; + getContext().pImpl->FunctionMetadata.erase(this); setHasMetadataHashEntry(false); } diff --git a/contrib/llvm/lib/IR/MetadataImpl.h b/contrib/llvm/lib/IR/MetadataImpl.h new file mode 100644 index 0000000..662a50e --- /dev/null +++ b/contrib/llvm/lib/IR/MetadataImpl.h @@ -0,0 +1,46 @@ +//===- MetadataImpl.h - Helpers for implementing metadata -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file has private helpers for implementing metadata types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATAIMPL_H +#define LLVM_IR_METADATAIMPL_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/Metadata.h" + +namespace llvm { + +template <class T, class InfoT> +static T *getUniqued(DenseSet<T *, InfoT> &Store, + const typename InfoT::KeyTy &Key) { + auto I = Store.find_as(Key); + return I == Store.end() ? nullptr : *I; +} + +template <class T, class StoreT> +T *MDNode::storeImpl(T *N, StorageType Storage, StoreT &Store) { + switch (Storage) { + case Uniqued: + Store.insert(N); + break; + case Distinct: + N->storeDistinctInContext(); + break; + case Temporary: + break; + } + return N; +} + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/IR/MetadataTracking.cpp b/contrib/llvm/lib/IR/MetadataTracking.cpp index ba97ca0..47f0b93 100644 --- a/contrib/llvm/lib/IR/MetadataTracking.cpp +++ b/contrib/llvm/lib/IR/MetadataTracking.cpp @@ -17,11 +17,8 @@ using namespace llvm; ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) { - if (auto *N = dyn_cast<MDNode>(&MD)) { - if (auto *U = dyn_cast<UniquableMDNode>(N)) - return U->ReplaceableUses.get(); - return cast<MDNodeFwdDecl>(N); - } + if (auto *N = dyn_cast<MDNode>(&MD)) + return N->Context.getReplaceableUses(); return dyn_cast<ValueAsMetadata>(&MD); } diff --git a/contrib/llvm/lib/IR/Module.cpp b/contrib/llvm/lib/IR/Module.cpp index d32ffcd..043f74e 100644 --- a/contrib/llvm/lib/IR/Module.cpp +++ b/contrib/llvm/lib/IR/Module.cpp @@ -278,7 +278,7 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) { } bool Module::isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB) { - if (ConstantInt *Behavior = mdconst::dyn_extract<ConstantInt>(MD)) { + if (ConstantInt *Behavior = mdconst::dyn_extract_or_null<ConstantInt>(MD)) { uint64_t Val = Behavior->getLimitedValue(); if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) { MFB = static_cast<ModFlagBehavior>(Val); @@ -298,7 +298,7 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { ModFlagBehavior MFB; if (Flag->getNumOperands() >= 3 && isValidModFlagBehavior(Flag->getOperand(0), MFB) && - isa<MDString>(Flag->getOperand(1))) { + dyn_cast_or_null<MDString>(Flag->getOperand(1))) { // Check the operands of the MDNode before accessing the operands. // The verifier will actually catch these failures. MDString *Key = cast<MDString>(Flag->getOperand(1)); @@ -365,31 +365,11 @@ void Module::addModuleFlag(MDNode *Node) { void Module::setDataLayout(StringRef Desc) { DL.reset(Desc); - - if (Desc.empty()) { - DataLayoutStr = ""; - } else { - DataLayoutStr = DL.getStringRepresentation(); - // DataLayoutStr is now equivalent to Desc, but since the representation - // is not unique, they may not be identical. - } } -void Module::setDataLayout(const DataLayout *Other) { - if (!Other) { - DataLayoutStr = ""; - DL.reset(""); - } else { - DL = *Other; - DataLayoutStr = DL.getStringRepresentation(); - } -} +void Module::setDataLayout(const DataLayout &Other) { DL = Other; } -const DataLayout *Module::getDataLayout() const { - if (DataLayoutStr.empty()) - return nullptr; - return &DL; -} +const DataLayout &Module::getDataLayout() const { return DL; } //===----------------------------------------------------------------------===// // Methods to control the materialization of GlobalValues in the Module. @@ -414,15 +394,15 @@ std::error_code Module::materialize(GlobalValue *GV) { return Materializer->materialize(GV); } -void Module::Dematerialize(GlobalValue *GV) { +void Module::dematerialize(GlobalValue *GV) { if (Materializer) - return Materializer->Dematerialize(GV); + return Materializer->dematerialize(GV); } std::error_code Module::materializeAll() { if (!Materializer) return std::error_code(); - return Materializer->MaterializeModule(this); + return Materializer->materializeModule(this); } std::error_code Module::materializeAllPermanently() { @@ -433,6 +413,12 @@ std::error_code Module::materializeAllPermanently() { return std::error_code(); } +std::error_code Module::materializeMetadata() { + if (!Materializer) + return std::error_code(); + return Materializer->materializeMetadata(); +} + //===----------------------------------------------------------------------===// // Other module related stuff. // diff --git a/contrib/llvm/lib/IR/Operator.cpp b/contrib/llvm/lib/IR/Operator.cpp new file mode 100644 index 0000000..bea1f80 --- /dev/null +++ b/contrib/llvm/lib/IR/Operator.cpp @@ -0,0 +1,44 @@ +#include "llvm/IR/Operator.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Type.h" + +#include "ConstantsContext.h" + +namespace llvm { +Type *GEPOperator::getSourceElementType() const { + if (auto *I = dyn_cast<GetElementPtrInst>(this)) + return I->getSourceElementType(); + return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); +} + +bool GEPOperator::accumulateConstantOffset(const DataLayout &DL, + APInt &Offset) const { + assert(Offset.getBitWidth() == + DL.getPointerSizeInBits(getPointerAddressSpace()) && + "The offset must have exactly as many bits as our pointer."); + + for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); + GTI != GTE; ++GTI) { + ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); + if (!OpC) + return false; + if (OpC->isZero()) + continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + unsigned ElementIdx = OpC->getZExtValue(); + const StructLayout *SL = DL.getStructLayout(STy); + Offset += APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)); + continue; + } + + // For array or vector indices, scale the index by the size of the type. + APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); + Offset += Index * APInt(Offset.getBitWidth(), + DL.getTypeAllocSize(GTI.getIndexedType())); + } + return true; +} +} // namespace llvm diff --git a/contrib/llvm/lib/IR/Pass.cpp b/contrib/llvm/lib/IR/Pass.cpp index 91d86ae..2fa1e7c 100644 --- a/contrib/llvm/lib/IR/Pass.cpp +++ b/contrib/llvm/lib/IR/Pass.cpp @@ -223,8 +223,8 @@ void PassRegistrationListener::enumeratePasses() { PassRegistry::getPassRegistry()->enumerateWith(this); } -PassNameParser::PassNameParser() - : Opt(nullptr) { +PassNameParser::PassNameParser(cl::Option &O) + : cl::parser<const PassInfo *>(O) { PassRegistry::getPassRegistry()->addRegistrationListener(this); } @@ -249,7 +249,7 @@ namespace { CFGOnlyList.push_back(P->getTypeInfo()); } }; -} +} // namespace // setPreservesCFG - This function should be called to by the pass, iff they do // not: diff --git a/contrib/llvm/lib/IR/Statepoint.cpp b/contrib/llvm/lib/IR/Statepoint.cpp index 270c016..83ee611 100644 --- a/contrib/llvm/lib/IR/Statepoint.cpp +++ b/contrib/llvm/lib/IR/Statepoint.cpp @@ -20,24 +20,34 @@ using namespace std; using namespace llvm; bool llvm::isStatepoint(const ImmutableCallSite &CS) { + if (!CS.getInstruction()) { + // This is not a call site + return false; + } + const Function *F = CS.getCalledFunction(); return (F && F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint); } -bool llvm::isStatepoint(const Instruction *inst) { +bool llvm::isStatepoint(const Value *inst) { if (isa<InvokeInst>(inst) || isa<CallInst>(inst)) { ImmutableCallSite CS(inst); return isStatepoint(CS); } return false; } -bool llvm::isStatepoint(const Instruction &inst) { +bool llvm::isStatepoint(const Value &inst) { return isStatepoint(&inst); } bool llvm::isGCRelocate(const ImmutableCallSite &CS) { + if (!CS.getInstruction()) { + // This is not a call site + return false; + } + return isGCRelocate(CS.getInstruction()); } -bool llvm::isGCRelocate(const Instruction *inst) { +bool llvm::isGCRelocate(const Value *inst) { if (const CallInst *call = dyn_cast<CallInst>(inst)) { if (const Function *F = call->getCalledFunction()) { return F->getIntrinsicID() == Intrinsic::experimental_gc_relocate; @@ -47,14 +57,20 @@ bool llvm::isGCRelocate(const Instruction *inst) { } bool llvm::isGCResult(const ImmutableCallSite &CS) { + if (!CS.getInstruction()) { + // This is not a call site + return false; + } + return isGCResult(CS.getInstruction()); } -bool llvm::isGCResult(const Instruction *inst) { +bool llvm::isGCResult(const Value *inst) { if (const CallInst *call = dyn_cast<CallInst>(inst)) { if (Function *F = call->getCalledFunction()) { return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int || F->getIntrinsicID() == Intrinsic::experimental_gc_result_float || - F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr); + F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr || + F->getIntrinsicID() == Intrinsic::experimental_gc_result); } } return false; diff --git a/contrib/llvm/lib/IR/SymbolTableListTraitsImpl.h b/contrib/llvm/lib/IR/SymbolTableListTraitsImpl.h index a18f982..f94def7 100644 --- a/contrib/llvm/lib/IR/SymbolTableListTraitsImpl.h +++ b/contrib/llvm/lib/IR/SymbolTableListTraitsImpl.h @@ -113,6 +113,6 @@ void SymbolTableListTraits<ValueSubClass,ItemParentClass> } } -} // End llvm namespace +} // namespace llvm #endif diff --git a/contrib/llvm/lib/IR/Type.cpp b/contrib/llvm/lib/IR/Type.cpp index 65060dc..b5c4e5d 100644 --- a/contrib/llvm/lib/IR/Type.cpp +++ b/contrib/llvm/lib/IR/Type.cpp @@ -238,6 +238,7 @@ IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; } IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; } IntegerType *Type::getInt32Ty(LLVMContext &C) { return &C.pImpl->Int32Ty; } IntegerType *Type::getInt64Ty(LLVMContext &C) { return &C.pImpl->Int64Ty; } +IntegerType *Type::getInt128Ty(LLVMContext &C) { return &C.pImpl->Int128Ty; } IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) { return IntegerType::get(C, N); @@ -306,12 +307,13 @@ IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { // Check for the built-in integer types switch (NumBits) { - case 1: return cast<IntegerType>(Type::getInt1Ty(C)); - case 8: return cast<IntegerType>(Type::getInt8Ty(C)); - case 16: return cast<IntegerType>(Type::getInt16Ty(C)); - case 32: return cast<IntegerType>(Type::getInt32Ty(C)); - case 64: return cast<IntegerType>(Type::getInt64Ty(C)); - default: + case 1: return cast<IntegerType>(Type::getInt1Ty(C)); + case 8: return cast<IntegerType>(Type::getInt8Ty(C)); + case 16: return cast<IntegerType>(Type::getInt16Ty(C)); + case 32: return cast<IntegerType>(Type::getInt32Ty(C)); + case 64: return cast<IntegerType>(Type::getInt64Ty(C)); + case 128: return cast<IntegerType>(Type::getInt128Ty(C)); + default: break; } @@ -764,3 +766,7 @@ bool PointerType::isValidElementType(Type *ElemTy) { return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && !ElemTy->isMetadataTy(); } + +bool PointerType::isLoadableOrStorableType(Type *ElemTy) { + return isValidElementType(ElemTy) && !ElemTy->isFunctionTy(); +} diff --git a/contrib/llvm/lib/IR/TypeFinder.cpp b/contrib/llvm/lib/IR/TypeFinder.cpp index e2fb8f8..7accc5b 100644 --- a/contrib/llvm/lib/IR/TypeFinder.cpp +++ b/contrib/llvm/lib/IR/TypeFinder.cpp @@ -50,6 +50,9 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { if (FI->hasPrologueData()) incorporateValue(FI->getPrologueData()); + if (FI->hasPersonalityFn()) + incorporateValue(FI->getPersonalityFn()); + // First incorporate the arguments. for (Function::const_arg_iterator AI = FI->arg_begin(), AE = FI->arg_end(); AI != AE; ++AI) @@ -68,7 +71,7 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { // instructions with this loop.) for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); OI != OE; ++OI) - if (!isa<Instruction>(OI)) + if (*OI && !isa<Instruction>(OI)) incorporateValue(*OI); // Incorporate types hiding in metadata. diff --git a/contrib/llvm/lib/IR/Use.cpp b/contrib/llvm/lib/IR/Use.cpp index cae845d..fd06fdb 100644 --- a/contrib/llvm/lib/IR/Use.cpp +++ b/contrib/llvm/lib/IR/Use.cpp @@ -124,4 +124,4 @@ const Use *Use::getImpliedUser() const { } } -} // End llvm namespace +} // namespace llvm diff --git a/contrib/llvm/lib/IR/UseListOrder.cpp b/contrib/llvm/lib/IR/UseListOrder.cpp deleted file mode 100644 index d064e67..0000000 --- a/contrib/llvm/lib/IR/UseListOrder.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===- 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/contrib/llvm/lib/IR/User.cpp b/contrib/llvm/lib/IR/User.cpp index ee83eacf..21f4849 100644 --- a/contrib/llvm/lib/IR/User.cpp +++ b/contrib/llvm/lib/IR/User.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/Operator.h" namespace llvm { +class BasicBlock; //===----------------------------------------------------------------------===// // User Class @@ -39,41 +40,100 @@ void User::replaceUsesOfWith(Value *From, Value *To) { // User allocHungoffUses Implementation //===----------------------------------------------------------------------===// -Use *User::allocHungoffUses(unsigned N) const { +void User::allocHungoffUses(unsigned N, bool IsPhi) { + assert(HasHungOffUses && "alloc must have hung off uses"); + + static_assert(AlignOf<Use>::Alignment >= AlignOf<Use::UserRef>::Alignment, + "Alignment is insufficient for 'hung-off-uses' pieces"); + static_assert(AlignOf<Use::UserRef>::Alignment >= + AlignOf<BasicBlock *>::Alignment, + "Alignment is insufficient for 'hung-off-uses' pieces"); + // Allocate the array of Uses, followed by a pointer (with bottom bit set) to // the User. size_t size = N * sizeof(Use) + sizeof(Use::UserRef); + if (IsPhi) + size += N * sizeof(BasicBlock *); Use *Begin = static_cast<Use*>(::operator new(size)); Use *End = Begin + N; (void) new(End) Use::UserRef(const_cast<User*>(this), 1); - return Use::initTags(Begin, End); + setOperandList(Use::initTags(Begin, End)); +} + +void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { + assert(HasHungOffUses && "realloc must have hung off uses"); + + unsigned OldNumUses = getNumOperands(); + + // We don't support shrinking the number of uses. We wouldn't have enough + // space to copy the old uses in to the new space. + assert(NewNumUses > OldNumUses && "realloc must grow num uses"); + + Use *OldOps = getOperandList(); + allocHungoffUses(NewNumUses, IsPhi); + Use *NewOps = getOperandList(); + + // Now copy from the old operands list to the new one. + std::copy(OldOps, OldOps + OldNumUses, NewOps); + + // If this is a Phi, then we need to copy the BB pointers too. + if (IsPhi) { + auto *OldPtr = + reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef); + auto *NewPtr = + reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef); + std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); + } + Use::zap(OldOps, OldOps + OldNumUses, true); } //===----------------------------------------------------------------------===// // User operator new Implementations //===----------------------------------------------------------------------===// -void *User::operator new(size_t s, unsigned Us) { - void *Storage = ::operator new(s + sizeof(Use) * Us); +void *User::operator new(size_t Size, unsigned Us) { + assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); + void *Storage = ::operator new(Size + sizeof(Use) * Us); Use *Start = static_cast<Use*>(Storage); Use *End = Start + Us; User *Obj = reinterpret_cast<User*>(End); - Obj->OperandList = Start; - Obj->NumOperands = Us; + Obj->NumUserOperands = Us; + Obj->HasHungOffUses = false; Use::initTags(Start, End); return Obj; } +void *User::operator new(size_t Size) { + // Allocate space for a single Use* + void *Storage = ::operator new(Size + sizeof(Use *)); + Use **HungOffOperandList = static_cast<Use **>(Storage); + User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); + Obj->NumUserOperands = 0; + Obj->HasHungOffUses = true; + *HungOffOperandList = nullptr; + return Obj; +} + //===----------------------------------------------------------------------===// // User operator delete Implementation //===----------------------------------------------------------------------===// void User::operator delete(void *Usr) { - User *Start = static_cast<User*>(Usr); - Use *Storage = static_cast<Use*>(Usr) - Start->NumOperands; - // If there were hung-off uses, they will have been freed already and - // NumOperands reset to 0, so here we just free the User itself. - ::operator delete(Storage); + // Hung off uses use a single Use* before the User, while other subclasses + // use a Use[] allocated prior to the user. + User *Obj = static_cast<User *>(Usr); + if (Obj->HasHungOffUses) { + Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; + // drop the hung off uses. + Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, + /* Delete */ true); + ::operator delete(HungOffOperandList); + } else { + Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; + Use::zap(Storage, Storage + Obj->NumUserOperands, + /* Delete */ false); + ::operator delete(Storage); + } } //===----------------------------------------------------------------------===// @@ -84,4 +144,4 @@ Operator::~Operator() { llvm_unreachable("should never destroy an Operator"); } -} // End llvm namespace +} // namespace llvm diff --git a/contrib/llvm/lib/IR/Value.cpp b/contrib/llvm/lib/IR/Value.cpp index 5f7e258..eb5c225 100644 --- a/contrib/llvm/lib/IR/Value.cpp +++ b/contrib/llvm/lib/IR/Value.cpp @@ -23,19 +23,23 @@ #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/Statepoint.h" #include "llvm/IR/ValueHandle.h" #include "llvm/IR/ValueSymbolTable.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace llvm; //===----------------------------------------------------------------------===// // Value Class //===----------------------------------------------------------------------===// +const unsigned Value::NumUserOperandsBits; static inline Type *checkType(Type *Ty) { assert(Ty && "Value defined with a null type: Error!"); @@ -43,8 +47,9 @@ static inline Type *checkType(Type *Ty) { } Value::Value(Type *ty, unsigned scid) - : VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), HasValueHandle(0), - SubclassOptionalData(0), SubclassData(0), NumOperands(0) { + : VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), + HasValueHandle(0), SubclassOptionalData(0), SubclassData(0), + NumUserOperands(0), IsUsedByMD(false), HasName(false) { // FIXME: Why isn't this in the subclass gunk?? // Note, we cannot call isa<CallInst> before the CallInst has been // constructed. @@ -67,15 +72,13 @@ Value::~Value() { #ifndef NDEBUG // Only in -g mode... // Check to make sure that there are no uses of this value that are still // around when the value is destroyed. If there are, then we have a dangling - // reference and something is wrong. This code is here to print out what is - // still being referenced. The value in question should be printed as - // a <badref> + // reference and something is wrong. This code is here to print out where + // the value is still being referenced. // if (!use_empty()) { dbgs() << "While deleting: " << *VTy << " %" << getName() << "\n"; - for (use_iterator I = use_begin(), E = use_end(); I != E; ++I) - dbgs() << "Use still stuck around after Def is destroyed:" - << **I << "\n"; + for (auto *U : users()) + dbgs() << "Use still stuck around after Def is destroyed:" << *U << "\n"; } #endif assert(use_empty() && "Uses remain when a value is destroyed!"); @@ -156,16 +159,44 @@ static bool getSymTab(Value *V, ValueSymbolTable *&ST) { return false; } +ValueName *Value::getValueName() const { + if (!HasName) return nullptr; + + LLVMContext &Ctx = getContext(); + auto I = Ctx.pImpl->ValueNames.find(this); + assert(I != Ctx.pImpl->ValueNames.end() && + "No name entry found!"); + + return I->second; +} + +void Value::setValueName(ValueName *VN) { + LLVMContext &Ctx = getContext(); + + assert(HasName == Ctx.pImpl->ValueNames.count(this) && + "HasName bit out of sync!"); + + if (!VN) { + if (HasName) + Ctx.pImpl->ValueNames.erase(this); + HasName = false; + return; + } + + HasName = true; + Ctx.pImpl->ValueNames[this] = VN; +} + StringRef Value::getName() const { // Make sure the empty string is still a C string. For historical reasons, // some clients want to call .data() on the result and expect it to be null // terminated. - if (!getValueName()) + if (!hasName()) return StringRef("", 0); return getValueName()->getKey(); } -void Value::setName(const Twine &NewName) { +void Value::setNameImpl(const Twine &NewName) { // Fast path for common IRBuilder case of setName("") when there is no name. if (NewName.isTriviallyEmpty() && !hasName()) return; @@ -186,9 +217,6 @@ void Value::setName(const Twine &NewName) { if (getSymTab(this, ST)) return; // Cannot set a name on this value (e.g. constant). - if (Function *F = dyn_cast<Function>(this)) - getContext().pImpl->IntrinsicIDCache.erase(F); - if (!ST) { // No symbol table to update? Just do the change. if (NameRef.empty()) { // Free the name for this value. @@ -221,6 +249,12 @@ void Value::setName(const Twine &NewName) { setValueName(ST->createValueName(NameRef, this)); } +void Value::setName(const Twine &NewName) { + setNameImpl(NewName); + if (Function *F = dyn_cast<Function>(this)) + F->recalculateIntrinsicID(); +} + void Value::takeName(Value *V) { ValueSymbolTable *ST = nullptr; // If this value has a name, drop it. @@ -476,133 +510,6 @@ Value *Value::stripInBoundsOffsets() { return stripPointerCastsAndOffsets<PSK_InBounds>(this); } -/// \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, - SmallPtrSetImpl<const Value *> &Visited) { - // Note that it is not safe to speculate into a malloc'd region because - // malloc may return null. - - // These are obviously ok. - if (isa<AllocaInst>(V)) return true; - - // It's not always safe to follow a bitcast, for example: - // bitcast i8* (alloca i8) to i32* - // would result in a 4-byte load from a 1-byte alloca. However, - // if we're casting from a pointer from a type of larger size - // to a type of smaller size (or the same size), and the alignment - // is at least as large as for the resulting pointer type, then - // we can look through the bitcast. - if (DL) - if (const BitCastInst* BC = dyn_cast<BitCastInst>(V)) { - Type *STy = BC->getSrcTy()->getPointerElementType(), - *DTy = BC->getDestTy()->getPointerElementType(); - if (STy->isSized() && DTy->isSized() && - (DL->getTypeStoreSize(STy) >= - DL->getTypeStoreSize(DTy)) && - (DL->getABITypeAlignment(STy) >= - DL->getABITypeAlignment(DTy))) - return isDereferenceablePointer(BC->getOperand(0), DL, Visited); - } - - // Global variables which can't collapse to null are ok. - if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) - return !GV->hasExternalWeakLinkage(); - - // 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)).second) - return false; - if (!isDereferenceablePointer(GEP->getOperand(0), DL, Visited)) - return false; - // Check the indices. - gep_type_iterator GTI = gep_type_begin(GEP); - for (User::const_op_iterator I = GEP->op_begin()+1, - E = GEP->op_end(); I != E; ++I) { - Value *Index = *I; - Type *Ty = *GTI++; - // Struct indices can't be out of bounds. - if (isa<StructType>(Ty)) - continue; - ConstantInt *CI = dyn_cast<ConstantInt>(Index); - if (!CI) - return false; - // Zero is always ok. - if (CI->isZero()) - continue; - // Check to see that it's within the bounds of an array. - ArrayType *ATy = dyn_cast<ArrayType>(Ty); - if (!ATy) - return false; - if (CI->getValue().getActiveBits() > 64) - return false; - if (CI->getZExtValue() >= ATy->getNumElements()) - return false; - } - // Indices check out; this is dereferenceable. - 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; -} - -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); -} - Value *Value::DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) { PHINode *PN = dyn_cast<PHINode>(this); diff --git a/contrib/llvm/lib/IR/ValueSymbolTable.cpp b/contrib/llvm/lib/IR/ValueSymbolTable.cpp index 4f078f0..e10142d 100644 --- a/contrib/llvm/lib/IR/ValueSymbolTable.cpp +++ b/contrib/llvm/lib/IR/ValueSymbolTable.cpp @@ -53,7 +53,7 @@ void ValueSymbolTable::reinsertValue(Value* V) { while (1) { // Trim any suffix off and append the next number. UniqueName.resize(BaseSize); - raw_svector_ostream(UniqueName) << ++LastUnique; + raw_svector_ostream(UniqueName) << "." << ++LastUnique; // Try insert the vmap entry with this suffix. auto IterBool = vmap.insert(std::make_pair(UniqueName, V)); diff --git a/contrib/llvm/lib/IR/ValueTypes.cpp b/contrib/llvm/lib/IR/ValueTypes.cpp index 2d4da95..d95de39 100644 --- a/contrib/llvm/lib/IR/ValueTypes.cpp +++ b/contrib/llvm/lib/IR/ValueTypes.cpp @@ -157,6 +157,7 @@ std::string EVT::getEVTString() const { case MVT::v4i64: return "v4i64"; case MVT::v8i64: return "v8i64"; case MVT::v16i64: return "v16i64"; + case MVT::v1i128: return "v1i128"; case MVT::v1f32: return "v1f32"; case MVT::v2f32: return "v2f32"; case MVT::v2f16: return "v2f16"; @@ -225,6 +226,7 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const { case MVT::v4i64: return VectorType::get(Type::getInt64Ty(Context), 4); case MVT::v8i64: return VectorType::get(Type::getInt64Ty(Context), 8); case MVT::v16i64: return VectorType::get(Type::getInt64Ty(Context), 16); + case MVT::v1i128: return VectorType::get(Type::getInt128Ty(Context), 1); case MVT::v2f16: return VectorType::get(Type::getHalfTy(Context), 2); case MVT::v4f16: return VectorType::get(Type::getHalfTy(Context), 4); case MVT::v8f16: return VectorType::get(Type::getHalfTy(Context), 8); diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp index 4bf2d1a..19b11b4 100644 --- a/contrib/llvm/lib/IR/Verifier.cpp +++ b/contrib/llvm/lib/IR/Verifier.cpp @@ -78,7 +78,7 @@ #include <cstdarg> using namespace llvm; -static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(false)); +static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true)); namespace { struct VerifierSupport { @@ -91,7 +91,8 @@ struct VerifierSupport { explicit VerifierSupport(raw_ostream &OS) : OS(OS), M(nullptr), Broken(false) {} - void WriteValue(const Value *V) { +private: + void Write(const Value *V) { if (!V) return; if (isa<Instruction>(V)) { @@ -102,81 +103,65 @@ struct VerifierSupport { } } - void WriteMetadata(const Metadata *MD) { + void Write(const Metadata *MD) { if (!MD) return; - MD->printAsOperand(OS, true, M); + MD->print(OS, M); OS << '\n'; } - void WriteType(Type *T) { + template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { + Write(MD.get()); + } + + void Write(const NamedMDNode *NMD) { + if (!NMD) + return; + NMD->print(OS); + OS << '\n'; + } + + void Write(Type *T) { if (!T) return; OS << ' ' << *T; } - void WriteComdat(const Comdat *C) { + void Write(const Comdat *C) { if (!C) return; OS << *C; } - // CheckFailed - A check failed, so print out the condition and the message - // that failed. This provides a nice place to put a breakpoint if you want - // to see why something is not correct. - void CheckFailed(const Twine &Message, const Value *V1 = nullptr, - const Value *V2 = nullptr, const Value *V3 = nullptr, - const Value *V4 = nullptr) { - OS << Message.str() << "\n"; - WriteValue(V1); - WriteValue(V2); - WriteValue(V3); - WriteValue(V4); - Broken = true; - } - - void CheckFailed(const Twine &Message, const Metadata *V1, const Metadata *V2, - const Metadata *V3 = nullptr, const Metadata *V4 = nullptr) { - OS << Message.str() << "\n"; - WriteMetadata(V1); - WriteMetadata(V2); - WriteMetadata(V3); - WriteMetadata(V4); - Broken = true; + template <typename T1, typename... Ts> + void WriteTs(const T1 &V1, const Ts &... Vs) { + Write(V1); + WriteTs(Vs...); } - void CheckFailed(const Twine &Message, const Metadata *V1, - const Value *V2 = nullptr) { - OS << Message.str() << "\n"; - WriteMetadata(V1); - WriteValue(V2); - Broken = true; - } + template <typename... Ts> void WriteTs() {} - void CheckFailed(const Twine &Message, const Value *V1, Type *T2, - const Value *V3 = nullptr) { - OS << Message.str() << "\n"; - WriteValue(V1); - WriteType(T2); - WriteValue(V3); - Broken = true; - } - - void CheckFailed(const Twine &Message, Type *T1, Type *T2 = nullptr, - Type *T3 = nullptr) { - OS << Message.str() << "\n"; - WriteType(T1); - WriteType(T2); - WriteType(T3); +public: + /// \brief A check failed, so printout out the condition and the message. + /// + /// This provides a nice place to put a breakpoint if you want to see why + /// something is not correct. + void CheckFailed(const Twine &Message) { + OS << Message << '\n'; Broken = true; } - void CheckFailed(const Twine &Message, const Comdat *C) { - OS << Message.str() << "\n"; - WriteComdat(C); - Broken = true; + /// \brief A check failed (with values to print). + /// + /// This calls the Message-only version so that the above is easier to set a + /// breakpoint on. + template <typename T1, typename... Ts> + void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { + CheckFailed(Message); + WriteTs(V1, Vs...); } }; + class Verifier : public InstVisitor<Verifier>, VerifierSupport { friend class InstVisitor<Verifier>; @@ -191,21 +176,22 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport { SmallPtrSet<Instruction *, 16> InstsInThisBlock; /// \brief Keep track of the metadata nodes that have been checked already. - SmallPtrSet<Metadata *, 32> MDNodes; + SmallPtrSet<const Metadata *, 32> MDNodes; - /// \brief The personality function referenced by the LandingPadInsts. - /// All LandingPadInsts within the same function must use the same - /// personality function. - const Value *PersonalityFn; + /// \brief Track unresolved string-based type references. + SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs; - /// \brief Whether we've seen a call to @llvm.frameallocate in this function + /// \brief Whether we've seen a call to @llvm.frameescape in this function /// already. - bool SawFrameAllocate; + bool SawFrameEscape; + + /// Stores the count of how many objects were passed to llvm.frameescape for a + /// given function and the largest index passed to llvm.framerecover. + DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo; public: - explicit Verifier(raw_ostream &OS = dbgs()) - : VerifierSupport(OS), Context(nullptr), PersonalityFn(nullptr), - SawFrameAllocate(false) {} + explicit Verifier(raw_ostream &OS) + : VerifierSupport(OS), Context(nullptr), SawFrameEscape(false) {} bool verify(const Function &F) { M = F.getParent(); @@ -239,8 +225,7 @@ public: // FIXME: We strip const here because the inst visitor strips const. visit(const_cast<Function &>(F)); InstsInThisBlock.clear(); - PersonalityFn = nullptr; - SawFrameAllocate = false; + SawFrameEscape = false; return !Broken; } @@ -259,6 +244,10 @@ public: visitFunction(*I); } + // Now that we've visited every function, verify that we never asked to + // recover a frame index that wasn't escaped. + verifyFrameRecoverIndices(); + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) visitGlobalVariable(*I); @@ -278,6 +267,9 @@ public: visitModuleFlags(M); visitModuleIdents(M); + // Verify type referneces last. + verifyTypeRefs(); + return !Broken; } @@ -290,9 +282,9 @@ private: void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, const GlobalAlias &A, const Constant &C); void visitNamedMDNode(const NamedMDNode &NMD); - void visitMDNode(MDNode &MD); - void visitMetadataAsValue(MetadataAsValue &MD, Function *F); - void visitValueAsMetadata(ValueAsMetadata &MD, Function *F); + void visitMDNode(const MDNode &MD); + void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); + void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); void visitComdat(const Comdat &C); void visitModuleIdents(const Module &M); void visitModuleFlags(const Module &M); @@ -303,6 +295,37 @@ private: void visitBasicBlock(BasicBlock &BB); void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty); + template <class Ty> bool isValidMetadataArray(const MDTuple &N); +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); +#include "llvm/IR/Metadata.def" + void visitDIScope(const DIScope &N); + void visitDIDerivedTypeBase(const DIDerivedTypeBase &N); + void visitDIVariable(const DIVariable &N); + void visitDILexicalBlockBase(const DILexicalBlockBase &N); + void visitDITemplateParameter(const DITemplateParameter &N); + + void visitTemplateParams(const MDNode &N, const Metadata &RawParams); + + /// \brief Check for a valid string-based type reference. + /// + /// Checks if \c MD is a string-based type reference. If it is, keeps track + /// of it (and its user, \c N) for error messages later. + bool isValidUUID(const MDNode &N, const Metadata *MD); + + /// \brief Check for a valid type reference. + /// + /// Checks for subclasses of \a DIType, or \a isValidUUID(). + bool isTypeRef(const MDNode &N, const Metadata *MD); + + /// \brief Check for a valid scope reference. + /// + /// Checks for subclasses of \a DIScope, or \a isValidUUID(). + bool isScopeRef(const MDNode &N, const Metadata *MD); + + /// \brief Check for a valid debug info reference. + /// + /// Checks for subclasses of \a DINode, or \a isValidUUID(). + bool isDIRef(const MDNode &N, const Metadata *MD); // InstVisitor overrides... using InstVisitor<Verifier>::visit; @@ -345,6 +368,8 @@ private: void visitUserOp1(Instruction &I); void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI); + template <class DbgIntrinsicTy> + void visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII); void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); void visitAtomicRMWInst(AtomicRMWInst &RMWI); void visitFenceInst(FenceInst &FI); @@ -368,136 +393,124 @@ private: bool isReturnValue, const Value *V); void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V); + void VerifyFunctionMetadata( + const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs); void VerifyConstantExprBitcastType(const ConstantExpr *CE); -}; -class DebugInfoVerifier : public VerifierSupport { -public: - explicit DebugInfoVerifier(raw_ostream &OS = dbgs()) : VerifierSupport(OS) {} - - bool verify(const Module &M) { - this->M = &M; - verifyDebugInfo(); - return !Broken; - } - -private: - void verifyDebugInfo(); - void processInstructions(DebugInfoFinder &Finder); - void processCallInst(DebugInfoFinder &Finder, const CallInst &CI); + void VerifyStatepoint(ImmutableCallSite CS); + void verifyFrameRecoverIndices(); + + // Module-level debug info verification... + void verifyTypeRefs(); + template <class MapTy> + void verifyBitPieceExpression(const DbgInfoIntrinsic &I, + const MapTy &TypeRefs); + void visitUnresolvedTypeRef(const MDString *S, const MDNode *N); }; } // End anonymous namespace // Assert - We know that cond should be true, if not print an error message. -#define Assert(C, M) \ - do { if (!(C)) { CheckFailed(M); return; } } while (0) -#define Assert1(C, M, V1) \ - do { if (!(C)) { CheckFailed(M, V1); return; } } while (0) -#define Assert2(C, M, V1, V2) \ - do { if (!(C)) { CheckFailed(M, V1, V2); return; } } while (0) -#define Assert3(C, M, V1, V2, V3) \ - do { if (!(C)) { CheckFailed(M, V1, V2, V3); return; } } while (0) -#define Assert4(C, M, V1, V2, V3, V4) \ - do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0) +#define Assert(C, ...) \ + do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (0) void Verifier::visit(Instruction &I) { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) - Assert1(I.getOperand(i) != nullptr, "Operand is null", &I); + Assert(I.getOperand(i) != nullptr, "Operand is null", &I); InstVisitor<Verifier>::visit(I); } void Verifier::visitGlobalValue(const GlobalValue &GV) { - Assert1(!GV.isDeclaration() || GV.hasExternalLinkage() || - GV.hasExternalWeakLinkage(), - "Global is external, but doesn't have external or weak linkage!", - &GV); + Assert(!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); + Assert(GV.getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &GV); + Assert(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV), + "Only global variables can have appending linkage!", &GV); if (GV.hasAppendingLinkage()) { const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV); - Assert1(GVar && GVar->getType()->getElementType()->isArrayTy(), - "Only global arrays can have appending linkage!", GVar); + Assert(GVar && GVar->getValueType()->isArrayTy(), + "Only global arrays can have appending linkage!", GVar); } } void Verifier::visitGlobalVariable(const GlobalVariable &GV) { if (GV.hasInitializer()) { - Assert1(GV.getInitializer()->getType() == GV.getType()->getElementType(), - "Global variable initializer type does not match global " - "variable type!", &GV); + Assert(GV.getInitializer()->getType() == GV.getType()->getElementType(), + "Global variable initializer type does not match global " + "variable type!", + &GV); // If the global has common linkage, it must have a zero initializer and // cannot be constant. if (GV.hasCommonLinkage()) { - Assert1(GV.getInitializer()->isNullValue(), - "'common' global must have a zero initializer!", &GV); - Assert1(!GV.isConstant(), "'common' global may not be marked constant!", - &GV); - Assert1(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV); + Assert(GV.getInitializer()->isNullValue(), + "'common' global must have a zero initializer!", &GV); + Assert(!GV.isConstant(), "'common' global may not be marked constant!", + &GV); + Assert(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV); } } else { - Assert1(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), - "invalid linkage type for global declaration", &GV); + Assert(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), + "invalid linkage type for global declaration", &GV); } if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || GV.getName() == "llvm.global_dtors")) { - Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(), - "invalid linkage for intrinsic global variable", &GV); + Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(), + "invalid linkage for intrinsic global variable", &GV); // Don't worry about emitting an error for it not being an array, // visitGlobalValue will complain on appending non-array. - if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getType()->getElementType())) { + if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) { StructType *STy = dyn_cast<StructType>(ATy->getElementType()); PointerType *FuncPtrTy = FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo(); // FIXME: Reject the 2-field form in LLVM 4.0. - Assert1(STy && (STy->getNumElements() == 2 || - STy->getNumElements() == 3) && - STy->getTypeAtIndex(0u)->isIntegerTy(32) && - STy->getTypeAtIndex(1) == FuncPtrTy, - "wrong type for intrinsic global variable", &GV); + Assert(STy && + (STy->getNumElements() == 2 || STy->getNumElements() == 3) && + STy->getTypeAtIndex(0u)->isIntegerTy(32) && + STy->getTypeAtIndex(1) == FuncPtrTy, + "wrong type for intrinsic global variable", &GV); if (STy->getNumElements() == 3) { Type *ETy = STy->getTypeAtIndex(2); - Assert1(ETy->isPointerTy() && - cast<PointerType>(ETy)->getElementType()->isIntegerTy(8), - "wrong type for intrinsic global variable", &GV); + Assert(ETy->isPointerTy() && + cast<PointerType>(ETy)->getElementType()->isIntegerTy(8), + "wrong type for intrinsic global variable", &GV); } } } if (GV.hasName() && (GV.getName() == "llvm.used" || GV.getName() == "llvm.compiler.used")) { - Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(), - "invalid linkage for intrinsic global variable", &GV); - Type *GVType = GV.getType()->getElementType(); + Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(), + "invalid linkage for intrinsic global variable", &GV); + Type *GVType = GV.getValueType(); if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) { PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType()); - Assert1(PTy, "wrong type for intrinsic global variable", &GV); + Assert(PTy, "wrong type for intrinsic global variable", &GV); if (GV.hasInitializer()) { const Constant *Init = GV.getInitializer(); const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); - Assert1(InitArray, "wrong initalizer for intrinsic global variable", - Init); + Assert(InitArray, "wrong initalizer for intrinsic global variable", + Init); for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) { Value *V = Init->getOperand(i)->stripPointerCastsNoFollowAliases(); - Assert1( - isa<GlobalVariable>(V) || isa<Function>(V) || isa<GlobalAlias>(V), - "invalid llvm.used member", V); - Assert1(V->hasName(), "members of llvm.used must be named", V); + Assert(isa<GlobalVariable>(V) || isa<Function>(V) || + isa<GlobalAlias>(V), + "invalid llvm.used member", V); + Assert(V->hasName(), "members of llvm.used must be named", V); } } } } - Assert1(!GV.hasDLLImportStorageClass() || - (GV.isDeclaration() && GV.hasExternalLinkage()) || - GV.hasAvailableExternallyLinkage(), - "Global is marked as dllimport, but not external", &GV); + Assert(!GV.hasDLLImportStorageClass() || + (GV.isDeclaration() && GV.hasExternalLinkage()) || + GV.hasAvailableExternallyLinkage(), + "Global is marked as dllimport, but not external", &GV); if (!GV.hasInitializer()) { visitGlobalValue(GV); @@ -515,8 +528,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { continue; if (const User *U = dyn_cast<User>(V)) { - for (unsigned I = 0, N = U->getNumOperands(); I != N; ++I) - WorkStack.push_back(U->getOperand(I)); + WorkStack.append(U->op_begin(), U->op_end()); } if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { @@ -538,13 +550,13 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { 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); + Assert(!GV->isDeclaration(), "Alias must point to a definition", &GA); if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { - Assert1(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA); + Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA); - Assert1(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias", - &GA); + Assert(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias", + &GA); } else { // Only continue verifying subexpressions of GlobalAliases. // Do not recurse into global initializers. @@ -565,19 +577,17 @@ void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, } void Verifier::visitGlobalAlias(const GlobalAlias &GA) { - Assert1(!GA.getName().empty(), - "Alias name cannot be empty!", &GA); - Assert1(GlobalAlias::isValidLinkage(GA.getLinkage()), - "Alias should have private, internal, linkonce, weak, linkonce_odr, " - "weak_odr, or external linkage!", - &GA); + Assert(GlobalAlias::isValidLinkage(GA.getLinkage()), + "Alias should have private, internal, linkonce, weak, linkonce_odr, " + "weak_odr, or external linkage!", + &GA); const Constant *Aliasee = GA.getAliasee(); - Assert1(Aliasee, "Aliasee cannot be NULL!", &GA); - Assert1(GA.getType() == Aliasee->getType(), - "Alias and aliasee types should match!", &GA); + Assert(Aliasee, "Aliasee cannot be NULL!", &GA); + Assert(GA.getType() == Aliasee->getType(), + "Alias and aliasee types should match!", &GA); - Assert1(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee), - "Aliasee should be either GlobalValue or ConstantExpr", &GA); + Assert(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee), + "Aliasee should be either GlobalValue or ConstantExpr", &GA); visitAliaseeSubExpr(GA, *Aliasee); @@ -587,6 +597,11 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) { MDNode *MD = NMD.getOperand(i); + + if (NMD.getName() == "llvm.dbg.cu") { + Assert(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD); + } + if (!MD) continue; @@ -594,18 +609,30 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { } } -void Verifier::visitMDNode(MDNode &MD) { +void Verifier::visitMDNode(const MDNode &MD) { // 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).second) return; + switch (MD.getMetadataID()) { + default: + llvm_unreachable("Invalid MDNode subclass"); + case Metadata::MDTupleKind: + break; +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ + case Metadata::CLASS##Kind: \ + visit##CLASS(cast<CLASS>(MD)); \ + break; +#include "llvm/IR/Metadata.def" + } + for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) { Metadata *Op = MD.getOperand(i); if (!Op) continue; - Assert2(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!", - &MD, Op); + Assert(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!", + &MD, Op); if (auto *N = dyn_cast<MDNode>(Op)) { visitMDNode(*N); continue; @@ -617,26 +644,26 @@ void Verifier::visitMDNode(MDNode &MD) { } // Check these last, so we diagnose problems in operands first. - Assert1(!isa<MDNodeFwdDecl>(MD), "Expected no forward declarations!", &MD); - Assert1(MD.isResolved(), "All nodes should be resolved!", &MD); + Assert(!MD.isTemporary(), "Expected no forward declarations!", &MD); + Assert(MD.isResolved(), "All nodes should be resolved!", &MD); } -void Verifier::visitValueAsMetadata(ValueAsMetadata &MD, Function *F) { - Assert1(MD.getValue(), "Expected valid value", &MD); - Assert2(!MD.getValue()->getType()->isMetadataTy(), - "Unexpected metadata round-trip through values", &MD, MD.getValue()); +void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) { + Assert(MD.getValue(), "Expected valid value", &MD); + Assert(!MD.getValue()->getType()->isMetadataTy(), + "Unexpected metadata round-trip through values", &MD, MD.getValue()); auto *L = dyn_cast<LocalAsMetadata>(&MD); if (!L) return; - Assert1(F, "function-local metadata used outside a function", L); + Assert(F, "function-local metadata used outside a function", L); // If this was an instruction, bb, or argument, verify that it is in the // function that we expect. Function *ActualF = nullptr; if (Instruction *I = dyn_cast<Instruction>(L->getValue())) { - Assert2(I->getParent(), "function-local metadata not in basic block", L, I); + Assert(I->getParent(), "function-local metadata not in basic block", L, I); ActualF = I->getParent()->getParent(); } else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue())) ActualF = BB->getParent(); @@ -644,10 +671,10 @@ void Verifier::visitValueAsMetadata(ValueAsMetadata &MD, Function *F) { ActualF = A->getParent(); assert(ActualF && "Unimplemented function local metadata case!"); - Assert1(ActualF == F, "function-local metadata used in wrong function", L); + Assert(ActualF == F, "function-local metadata used in wrong function", L); } -void Verifier::visitMetadataAsValue(MetadataAsValue &MDV, Function *F) { +void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { Metadata *MD = MDV.getMetadata(); if (auto *N = dyn_cast<MDNode>(MD)) { visitMDNode(*N); @@ -663,19 +690,415 @@ void Verifier::visitMetadataAsValue(MetadataAsValue &MDV, Function *F) { visitValueAsMetadata(*V, F); } +bool Verifier::isValidUUID(const MDNode &N, const Metadata *MD) { + auto *S = dyn_cast<MDString>(MD); + if (!S) + return false; + if (S->getString().empty()) + return false; + + // Keep track of names of types referenced via UUID so we can check that they + // actually exist. + UnresolvedTypeRefs.insert(std::make_pair(S, &N)); + return true; +} + +/// \brief Check if a value can be a reference to a type. +bool Verifier::isTypeRef(const MDNode &N, const Metadata *MD) { + return !MD || isValidUUID(N, MD) || isa<DIType>(MD); +} + +/// \brief Check if a value can be a ScopeRef. +bool Verifier::isScopeRef(const MDNode &N, const Metadata *MD) { + return !MD || isValidUUID(N, MD) || isa<DIScope>(MD); +} + +/// \brief Check if a value can be a debug info ref. +bool Verifier::isDIRef(const MDNode &N, const Metadata *MD) { + return !MD || isValidUUID(N, MD) || isa<DINode>(MD); +} + +template <class Ty> +bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) { + for (Metadata *MD : N.operands()) { + if (MD) { + if (!isa<Ty>(MD)) + return false; + } else { + if (!AllowNull) + return false; + } + } + return true; +} + +template <class Ty> +bool isValidMetadataArray(const MDTuple &N) { + return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ false); +} + +template <class Ty> +bool isValidMetadataNullArray(const MDTuple &N) { + return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ true); +} + +void Verifier::visitDILocation(const DILocation &N) { + Assert(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "location requires a valid scope", &N, N.getRawScope()); + if (auto *IA = N.getRawInlinedAt()) + Assert(isa<DILocation>(IA), "inlined-at should be a location", &N, IA); +} + +void Verifier::visitGenericDINode(const GenericDINode &N) { + Assert(N.getTag(), "invalid tag", &N); +} + +void Verifier::visitDIScope(const DIScope &N) { + if (auto *F = N.getRawFile()) + Assert(isa<DIFile>(F), "invalid file", &N, F); +} + +void Verifier::visitDISubrange(const DISubrange &N) { + Assert(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N); + Assert(N.getCount() >= -1, "invalid subrange count", &N); +} + +void Verifier::visitDIEnumerator(const DIEnumerator &N) { + Assert(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N); +} + +void Verifier::visitDIBasicType(const DIBasicType &N) { + Assert(N.getTag() == dwarf::DW_TAG_base_type || + N.getTag() == dwarf::DW_TAG_unspecified_type, + "invalid tag", &N); +} + +void Verifier::visitDIDerivedTypeBase(const DIDerivedTypeBase &N) { + // Common scope checks. + visitDIScope(N); + + Assert(isScopeRef(N, N.getScope()), "invalid scope", &N, N.getScope()); + Assert(isTypeRef(N, N.getBaseType()), "invalid base type", &N, + N.getBaseType()); + + // FIXME: Sink this into the subclass verifies. + if (!N.getFile() || N.getFile()->getFilename().empty()) { + // Check whether the filename is allowed to be empty. + uint16_t Tag = N.getTag(); + Assert( + Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || + Tag == dwarf::DW_TAG_pointer_type || + Tag == dwarf::DW_TAG_ptr_to_member_type || + Tag == dwarf::DW_TAG_reference_type || + Tag == dwarf::DW_TAG_rvalue_reference_type || + Tag == dwarf::DW_TAG_restrict_type || + Tag == dwarf::DW_TAG_array_type || + Tag == dwarf::DW_TAG_enumeration_type || + Tag == dwarf::DW_TAG_subroutine_type || + Tag == dwarf::DW_TAG_inheritance || Tag == dwarf::DW_TAG_friend || + Tag == dwarf::DW_TAG_structure_type || + Tag == dwarf::DW_TAG_member || Tag == dwarf::DW_TAG_typedef, + "derived/composite type requires a filename", &N, N.getFile()); + } +} + +void Verifier::visitDIDerivedType(const DIDerivedType &N) { + // Common derived type checks. + visitDIDerivedTypeBase(N); + + Assert(N.getTag() == dwarf::DW_TAG_typedef || + N.getTag() == dwarf::DW_TAG_pointer_type || + N.getTag() == dwarf::DW_TAG_ptr_to_member_type || + N.getTag() == dwarf::DW_TAG_reference_type || + N.getTag() == dwarf::DW_TAG_rvalue_reference_type || + N.getTag() == dwarf::DW_TAG_const_type || + N.getTag() == dwarf::DW_TAG_volatile_type || + N.getTag() == dwarf::DW_TAG_restrict_type || + N.getTag() == dwarf::DW_TAG_member || + N.getTag() == dwarf::DW_TAG_inheritance || + N.getTag() == dwarf::DW_TAG_friend, + "invalid tag", &N); + if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { + Assert(isTypeRef(N, N.getExtraData()), "invalid pointer to member type", &N, + N.getExtraData()); + } +} + +static bool hasConflictingReferenceFlags(unsigned Flags) { + return (Flags & DINode::FlagLValueReference) && + (Flags & DINode::FlagRValueReference); +} + +void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) { + auto *Params = dyn_cast<MDTuple>(&RawParams); + Assert(Params, "invalid template params", &N, &RawParams); + for (Metadata *Op : Params->operands()) { + Assert(Op && isa<DITemplateParameter>(Op), "invalid template parameter", &N, + Params, Op); + } +} + +void Verifier::visitDICompositeType(const DICompositeType &N) { + // Common derived type checks. + visitDIDerivedTypeBase(N); + + Assert(N.getTag() == dwarf::DW_TAG_array_type || + N.getTag() == dwarf::DW_TAG_structure_type || + N.getTag() == dwarf::DW_TAG_union_type || + N.getTag() == dwarf::DW_TAG_enumeration_type || + N.getTag() == dwarf::DW_TAG_subroutine_type || + N.getTag() == dwarf::DW_TAG_class_type, + "invalid tag", &N); + + Assert(!N.getRawElements() || isa<MDTuple>(N.getRawElements()), + "invalid composite elements", &N, N.getRawElements()); + Assert(isTypeRef(N, N.getRawVTableHolder()), "invalid vtable holder", &N, + N.getRawVTableHolder()); + Assert(!N.getRawElements() || isa<MDTuple>(N.getRawElements()), + "invalid composite elements", &N, N.getRawElements()); + Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", + &N); + if (auto *Params = N.getRawTemplateParams()) + visitTemplateParams(N, *Params); +} + +void Verifier::visitDISubroutineType(const DISubroutineType &N) { + Assert(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N); + if (auto *Types = N.getRawTypeArray()) { + Assert(isa<MDTuple>(Types), "invalid composite elements", &N, Types); + for (Metadata *Ty : N.getTypeArray()->operands()) { + Assert(isTypeRef(N, Ty), "invalid subroutine type ref", &N, Types, Ty); + } + } + Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", + &N); +} + +void Verifier::visitDIFile(const DIFile &N) { + Assert(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N); +} + +void Verifier::visitDICompileUnit(const DICompileUnit &N) { + Assert(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N); + + // Don't bother verifying the compilation directory or producer string + // as those could be empty. + Assert(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N, + N.getRawFile()); + Assert(!N.getFile()->getFilename().empty(), "invalid filename", &N, + N.getFile()); + + if (auto *Array = N.getRawEnumTypes()) { + Assert(isa<MDTuple>(Array), "invalid enum list", &N, Array); + for (Metadata *Op : N.getEnumTypes()->operands()) { + auto *Enum = dyn_cast_or_null<DICompositeType>(Op); + Assert(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type, + "invalid enum type", &N, N.getEnumTypes(), Op); + } + } + if (auto *Array = N.getRawRetainedTypes()) { + Assert(isa<MDTuple>(Array), "invalid retained type list", &N, Array); + for (Metadata *Op : N.getRetainedTypes()->operands()) { + Assert(Op && isa<DIType>(Op), "invalid retained type", &N, Op); + } + } + if (auto *Array = N.getRawSubprograms()) { + Assert(isa<MDTuple>(Array), "invalid subprogram list", &N, Array); + for (Metadata *Op : N.getSubprograms()->operands()) { + Assert(Op && isa<DISubprogram>(Op), "invalid subprogram ref", &N, Op); + } + } + if (auto *Array = N.getRawGlobalVariables()) { + Assert(isa<MDTuple>(Array), "invalid global variable list", &N, Array); + for (Metadata *Op : N.getGlobalVariables()->operands()) { + Assert(Op && isa<DIGlobalVariable>(Op), "invalid global variable ref", &N, + Op); + } + } + if (auto *Array = N.getRawImportedEntities()) { + Assert(isa<MDTuple>(Array), "invalid imported entity list", &N, Array); + for (Metadata *Op : N.getImportedEntities()->operands()) { + Assert(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref", &N, + Op); + } + } +} + +void Verifier::visitDISubprogram(const DISubprogram &N) { + Assert(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N); + Assert(isScopeRef(N, N.getRawScope()), "invalid scope", &N, N.getRawScope()); + if (auto *T = N.getRawType()) + Assert(isa<DISubroutineType>(T), "invalid subroutine type", &N, T); + Assert(isTypeRef(N, N.getRawContainingType()), "invalid containing type", &N, + N.getRawContainingType()); + if (auto *RawF = N.getRawFunction()) { + auto *FMD = dyn_cast<ConstantAsMetadata>(RawF); + auto *F = FMD ? FMD->getValue() : nullptr; + auto *FT = F ? dyn_cast<PointerType>(F->getType()) : nullptr; + Assert(F && FT && isa<FunctionType>(FT->getElementType()), + "invalid function", &N, F, FT); + } + if (auto *Params = N.getRawTemplateParams()) + visitTemplateParams(N, *Params); + if (auto *S = N.getRawDeclaration()) { + Assert(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(), + "invalid subprogram declaration", &N, S); + } + if (auto *RawVars = N.getRawVariables()) { + auto *Vars = dyn_cast<MDTuple>(RawVars); + Assert(Vars, "invalid variable list", &N, RawVars); + for (Metadata *Op : Vars->operands()) { + Assert(Op && isa<DILocalVariable>(Op), "invalid local variable", &N, Vars, + Op); + } + } + Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", + &N); + + auto *F = N.getFunction(); + if (!F) + return; + + // Check that all !dbg attachments lead to back to N (or, at least, another + // subprogram that describes the same function). + // + // FIXME: Check this incrementally while visiting !dbg attachments. + // FIXME: Only check when N is the canonical subprogram for F. + SmallPtrSet<const MDNode *, 32> Seen; + for (auto &BB : *F) + for (auto &I : BB) { + // Be careful about using DILocation here since we might be dealing with + // broken code (this is the Verifier after all). + DILocation *DL = + dyn_cast_or_null<DILocation>(I.getDebugLoc().getAsMDNode()); + if (!DL) + continue; + if (!Seen.insert(DL).second) + continue; + + DILocalScope *Scope = DL->getInlinedAtScope(); + if (Scope && !Seen.insert(Scope).second) + continue; + + DISubprogram *SP = Scope ? Scope->getSubprogram() : nullptr; + if (SP && !Seen.insert(SP).second) + continue; + + // FIXME: Once N is canonical, check "SP == &N". + Assert(SP->describes(F), + "!dbg attachment points at wrong subprogram for function", &N, F, + &I, DL, Scope, SP); + } +} + +void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { + Assert(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); + Assert(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "invalid local scope", &N, N.getRawScope()); +} + +void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { + visitDILexicalBlockBase(N); + + Assert(N.getLine() || !N.getColumn(), + "cannot have column info without line info", &N); +} + +void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { + visitDILexicalBlockBase(N); +} + +void Verifier::visitDINamespace(const DINamespace &N) { + Assert(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N); + if (auto *S = N.getRawScope()) + Assert(isa<DIScope>(S), "invalid scope ref", &N, S); +} + +void Verifier::visitDITemplateParameter(const DITemplateParameter &N) { + Assert(isTypeRef(N, N.getType()), "invalid type ref", &N, N.getType()); +} + +void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) { + visitDITemplateParameter(N); + + Assert(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag", + &N); +} + +void Verifier::visitDITemplateValueParameter( + const DITemplateValueParameter &N) { + visitDITemplateParameter(N); + + Assert(N.getTag() == dwarf::DW_TAG_template_value_parameter || + N.getTag() == dwarf::DW_TAG_GNU_template_template_param || + N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack, + "invalid tag", &N); +} + +void Verifier::visitDIVariable(const DIVariable &N) { + if (auto *S = N.getRawScope()) + Assert(isa<DIScope>(S), "invalid scope", &N, S); + Assert(isTypeRef(N, N.getRawType()), "invalid type ref", &N, N.getRawType()); + if (auto *F = N.getRawFile()) + Assert(isa<DIFile>(F), "invalid file", &N, F); +} + +void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { + // Checks common to all variables. + visitDIVariable(N); + + Assert(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); + Assert(!N.getName().empty(), "missing global variable name", &N); + if (auto *V = N.getRawVariable()) { + Assert(isa<ConstantAsMetadata>(V) && + !isa<Function>(cast<ConstantAsMetadata>(V)->getValue()), + "invalid global varaible ref", &N, V); + } + if (auto *Member = N.getRawStaticDataMemberDeclaration()) { + Assert(isa<DIDerivedType>(Member), "invalid static data member declaration", + &N, Member); + } +} + +void Verifier::visitDILocalVariable(const DILocalVariable &N) { + // Checks common to all variables. + visitDIVariable(N); + + Assert(N.getTag() == dwarf::DW_TAG_auto_variable || + N.getTag() == dwarf::DW_TAG_arg_variable, + "invalid tag", &N); + Assert(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "local variable requires a valid scope", &N, N.getRawScope()); +} + +void Verifier::visitDIExpression(const DIExpression &N) { + Assert(N.isValid(), "invalid expression", &N); +} + +void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { + Assert(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N); + if (auto *T = N.getRawType()) + Assert(isTypeRef(N, T), "invalid type ref", &N, T); + if (auto *F = N.getRawFile()) + Assert(isa<DIFile>(F), "invalid file", &N, F); +} + +void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { + Assert(N.getTag() == dwarf::DW_TAG_imported_module || + N.getTag() == dwarf::DW_TAG_imported_declaration, + "invalid tag", &N); + if (auto *S = N.getRawScope()) + Assert(isa<DIScope>(S), "invalid scope for imported entity", &N, S); + Assert(isDIRef(N, N.getEntity()), "invalid imported entity", &N, + N.getEntity()); +} + void Verifier::visitComdat(const Comdat &C) { - // All Comdat::SelectionKind values other than Comdat::Any require a - // GlobalValue with the same name as the Comdat. - const GlobalValue *GV = M->getNamedValue(C.getName()); - if (C.getSelectionKind() != Comdat::Any) - Assert1(GV, - "comdat selection kind requires a global value with the same name", - &C); // 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->hasPrivateLinkage(), "comdat global value has private linkage", - GV); + if (const GlobalValue *GV = M->getNamedValue(C.getName())) + Assert(!GV->hasPrivateLinkage(), "comdat global value has private linkage", + GV); } void Verifier::visitModuleIdents(const Module &M) { @@ -687,12 +1110,12 @@ void Verifier::visitModuleIdents(const Module &M) { // Scan each llvm.ident entry and make sure that this requirement is met. for (unsigned i = 0, e = Idents->getNumOperands(); i != e; ++i) { const MDNode *N = Idents->getOperand(i); - Assert1(N->getNumOperands() == 1, - "incorrect number of operands in llvm.ident metadata", N); - Assert1(isa<MDString>(N->getOperand(0)), - ("invalid value for llvm.ident metadata entry operand" - "(the operand should be a string)"), - N->getOperand(0)); + Assert(N->getNumOperands() == 1, + "incorrect number of operands in llvm.ident metadata", N); + Assert(dyn_cast_or_null<MDString>(N->getOperand(0)), + ("invalid value for llvm.ident metadata entry operand" + "(the operand should be a string)"), + N->getOperand(0)); } } @@ -735,22 +1158,21 @@ Verifier::visitModuleFlag(const MDNode *Op, SmallVectorImpl<const MDNode *> &Requirements) { // Each module flag should have three arguments, the merge behavior (a // constant int), the flag ID (an MDString), and the value. - Assert1(Op->getNumOperands() == 3, - "incorrect number of operands in module flag", Op); + Assert(Op->getNumOperands() == 3, + "incorrect number of operands in module flag", Op); Module::ModFlagBehavior MFB; if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { - Assert1( - mdconst::dyn_extract<ConstantInt>(Op->getOperand(0)), + Assert( + mdconst::dyn_extract_or_null<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)); + Assert(false, + "invalid behavior operand in module flag (unexpected constant)", + Op->getOperand(0)); } - MDString *ID = dyn_cast<MDString>(Op->getOperand(1)); - Assert1(ID, - "invalid ID operand in module flag (expected metadata string)", - Op->getOperand(1)); + MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1)); + Assert(ID, "invalid ID operand in module flag (expected metadata string)", + Op->getOperand(1)); // Sanity check the values for behaviors with additional requirements. switch (MFB) { @@ -764,13 +1186,13 @@ Verifier::visitModuleFlag(const MDNode *Op, // The value should itself be an MDNode with two operands, a flag ID (an // MDString), and a value. MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2)); - Assert1(Value && Value->getNumOperands() == 2, - "invalid value for 'require' module flag (expected metadata pair)", - Op->getOperand(2)); - Assert1(isa<MDString>(Value->getOperand(0)), - ("invalid value for 'require' module flag " - "(first value operand should be a string)"), - Value->getOperand(0)); + Assert(Value && Value->getNumOperands() == 2, + "invalid value for 'require' module flag (expected metadata pair)", + Op->getOperand(2)); + Assert(isa<MDString>(Value->getOperand(0)), + ("invalid value for 'require' module flag " + "(first value operand should be a string)"), + Value->getOperand(0)); // Append it to the list of requirements, to check once all module flags are // scanned. @@ -781,9 +1203,10 @@ Verifier::visitModuleFlag(const MDNode *Op, case Module::Append: case Module::AppendUnique: { // These behavior types require the operand be an MDNode. - Assert1(isa<MDNode>(Op->getOperand(2)), - "invalid value for 'append'-type module flag " - "(expected a metadata node)", Op->getOperand(2)); + Assert(isa<MDNode>(Op->getOperand(2)), + "invalid value for 'append'-type module flag " + "(expected a metadata node)", + Op->getOperand(2)); break; } } @@ -791,9 +1214,8 @@ Verifier::visitModuleFlag(const MDNode *Op, // Unless this is a "requires" flag, check the ID is unique. 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)", - ID); + Assert(Inserted, + "module flag identifiers must be unique (or of 'require' type)", ID); } } @@ -821,6 +1243,7 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, I->getKindAsEnum() == Attribute::StackProtect || I->getKindAsEnum() == Attribute::StackProtectReq || I->getKindAsEnum() == Attribute::StackProtectStrong || + I->getKindAsEnum() == Attribute::SafeStack || I->getKindAsEnum() == Attribute::NoRedZone || I->getKindAsEnum() == Attribute::NoImplicitFloat || I->getKindAsEnum() == Attribute::Naked || @@ -838,7 +1261,8 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, I->getKindAsEnum() == Attribute::NoBuiltin || I->getKindAsEnum() == Attribute::Cold || I->getKindAsEnum() == Attribute::OptimizeNone || - I->getKindAsEnum() == Attribute::JumpTable) { + I->getKindAsEnum() == Attribute::JumpTable || + I->getKindAsEnum() == Attribute::Convergent) { if (!isFunction) { CheckFailed("Attribute '" + I->getAsString() + "' only applies to functions!", V); @@ -869,14 +1293,15 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, VerifyAttributeTypes(Attrs, Idx, false, V); if (isReturnValue) - Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) && - !Attrs.hasAttribute(Idx, Attribute::Nest) && - !Attrs.hasAttribute(Idx, Attribute::StructRet) && - !Attrs.hasAttribute(Idx, Attribute::NoCapture) && - !Attrs.hasAttribute(Idx, Attribute::Returned) && - !Attrs.hasAttribute(Idx, Attribute::InAlloca), - "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', and " - "'returned' do not apply to return values!", V); + Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal) && + !Attrs.hasAttribute(Idx, Attribute::Nest) && + !Attrs.hasAttribute(Idx, Attribute::StructRet) && + !Attrs.hasAttribute(Idx, Attribute::NoCapture) && + !Attrs.hasAttribute(Idx, Attribute::Returned) && + !Attrs.hasAttribute(Idx, Attribute::InAlloca), + "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', and " + "'returned' do not apply to return values!", + V); // Check for mutually incompatible attributes. Only inreg is compatible with // sret. @@ -886,45 +1311,59 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, AttrCount += Attrs.hasAttribute(Idx, Attribute::StructRet) || Attrs.hasAttribute(Idx, Attribute::InReg); AttrCount += Attrs.hasAttribute(Idx, Attribute::Nest); - Assert1(AttrCount <= 1, "Attributes 'byval', 'inalloca', 'inreg', 'nest', " - "and 'sret' are incompatible!", V); - - Assert1(!(Attrs.hasAttribute(Idx, Attribute::InAlloca) && - Attrs.hasAttribute(Idx, Attribute::ReadOnly)), "Attributes " - "'inalloca and readonly' are incompatible!", V); - - Assert1(!(Attrs.hasAttribute(Idx, Attribute::StructRet) && - Attrs.hasAttribute(Idx, Attribute::Returned)), "Attributes " - "'sret and returned' are incompatible!", V); - - Assert1(!(Attrs.hasAttribute(Idx, Attribute::ZExt) && - Attrs.hasAttribute(Idx, Attribute::SExt)), "Attributes " - "'zeroext and signext' are incompatible!", V); - - Assert1(!(Attrs.hasAttribute(Idx, Attribute::ReadNone) && - Attrs.hasAttribute(Idx, Attribute::ReadOnly)), "Attributes " - "'readnone and readonly' are incompatible!", V); - - Assert1(!(Attrs.hasAttribute(Idx, Attribute::NoInline) && - Attrs.hasAttribute(Idx, Attribute::AlwaysInline)), "Attributes " - "'noinline and alwaysinline' are incompatible!", V); - - Assert1(!AttrBuilder(Attrs, Idx). - hasAttributes(AttributeFuncs::typeIncompatible(Ty, Idx), Idx), - "Wrong types for attribute: " + - AttributeFuncs::typeIncompatible(Ty, Idx).getAsString(Idx), V); + Assert(AttrCount <= 1, "Attributes 'byval', 'inalloca', 'inreg', 'nest', " + "and 'sret' are incompatible!", + V); + + Assert(!(Attrs.hasAttribute(Idx, Attribute::InAlloca) && + Attrs.hasAttribute(Idx, Attribute::ReadOnly)), + "Attributes " + "'inalloca and readonly' are incompatible!", + V); + + Assert(!(Attrs.hasAttribute(Idx, Attribute::StructRet) && + Attrs.hasAttribute(Idx, Attribute::Returned)), + "Attributes " + "'sret and returned' are incompatible!", + V); + + Assert(!(Attrs.hasAttribute(Idx, Attribute::ZExt) && + Attrs.hasAttribute(Idx, Attribute::SExt)), + "Attributes " + "'zeroext and signext' are incompatible!", + V); + + Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadNone) && + Attrs.hasAttribute(Idx, Attribute::ReadOnly)), + "Attributes " + "'readnone and readonly' are incompatible!", + V); + + Assert(!(Attrs.hasAttribute(Idx, Attribute::NoInline) && + Attrs.hasAttribute(Idx, Attribute::AlwaysInline)), + "Attributes " + "'noinline and alwaysinline' are incompatible!", + V); + + Assert(!AttrBuilder(Attrs, Idx) + .overlaps(AttributeFuncs::typeIncompatible(Ty)), + "Wrong types for attribute: " + + AttributeSet::get(*Context, Idx, + AttributeFuncs::typeIncompatible(Ty)).getAsString(Idx), + V); if (PointerType *PTy = dyn_cast<PointerType>(Ty)) { - if (!PTy->getElementType()->isSized()) { - Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) && - !Attrs.hasAttribute(Idx, Attribute::InAlloca), - "Attributes 'byval' and 'inalloca' do not support unsized types!", - V); + SmallPtrSet<const Type*, 4> Visited; + if (!PTy->getElementType()->isSized(&Visited)) { + Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal) && + !Attrs.hasAttribute(Idx, Attribute::InAlloca), + "Attributes 'byval' and 'inalloca' do not support unsized types!", + V); } } else { - Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal), - "Attribute 'byval' only applies to parameters with pointer type!", - V); + Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal), + "Attribute 'byval' only applies to parameters with pointer type!", + V); } } @@ -956,28 +1395,30 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, continue; if (Attrs.hasAttribute(Idx, Attribute::Nest)) { - Assert1(!SawNest, "More than one parameter has attribute nest!", V); + Assert(!SawNest, "More than one parameter has attribute nest!", V); SawNest = true; } if (Attrs.hasAttribute(Idx, Attribute::Returned)) { - Assert1(!SawReturned, "More than one parameter has attribute returned!", - V); - Assert1(Ty->canLosslesslyBitCastTo(FT->getReturnType()), "Incompatible " - "argument and return types for 'returned' attribute", V); + Assert(!SawReturned, "More than one parameter has attribute returned!", + V); + Assert(Ty->canLosslesslyBitCastTo(FT->getReturnType()), + "Incompatible " + "argument and return types for 'returned' attribute", + V); SawReturned = true; } if (Attrs.hasAttribute(Idx, Attribute::StructRet)) { - Assert1(!SawSRet, "Cannot have multiple 'sret' parameters!", V); - Assert1(Idx == 1 || Idx == 2, - "Attribute 'sret' is not on first or second parameter!", V); + Assert(!SawSRet, "Cannot have multiple 'sret' parameters!", V); + Assert(Idx == 1 || Idx == 2, + "Attribute 'sret' is not on first or second parameter!", V); SawSRet = true; } if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) { - Assert1(Idx == FT->getNumParams(), - "inalloca isn't on the last parameter!", V); + Assert(Idx == FT->getNumParams(), "inalloca isn't on the last parameter!", + V); } } @@ -986,39 +1427,65 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, VerifyAttributeTypes(Attrs, AttributeSet::FunctionIndex, true, V); - Assert1(!(Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ReadNone) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::ReadOnly)), - "Attributes 'readnone and readonly' are incompatible!", V); + Assert( + !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && + Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly)), + "Attributes 'readnone and readonly' are incompatible!", V); - Assert1(!(Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::NoInline) && - Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::AlwaysInline)), - "Attributes 'noinline and alwaysinline' are incompatible!", V); + Assert( + !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoInline) && + Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::AlwaysInline)), + "Attributes 'noinline and alwaysinline' are incompatible!", V); if (Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::OptimizeNone)) { - Assert1(Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::NoInline), - "Attribute 'optnone' requires 'noinline'!", V); + Assert(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoInline), + "Attribute 'optnone' requires 'noinline'!", V); - Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::OptimizeForSize), - "Attributes 'optsize and optnone' are incompatible!", V); + Assert(!Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::OptimizeForSize), + "Attributes 'optsize and optnone' are incompatible!", V); - Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::MinSize), - "Attributes 'minsize and optnone' are incompatible!", V); + Assert(!Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize), + "Attributes 'minsize and optnone' are incompatible!", V); } if (Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::JumpTable)) { const GlobalValue *GV = cast<GlobalValue>(V); - Assert1(GV->hasUnnamedAddr(), - "Attribute 'jumptable' requires 'unnamed_addr'", V); + Assert(GV->hasUnnamedAddr(), + "Attribute 'jumptable' requires 'unnamed_addr'", V); + } +} +void Verifier::VerifyFunctionMetadata( + const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs) { + if (MDs.empty()) + return; + + for (unsigned i = 0; i < MDs.size(); i++) { + if (MDs[i].first == LLVMContext::MD_prof) { + MDNode *MD = MDs[i].second; + Assert(MD->getNumOperands() == 2, + "!prof annotations should have exactly 2 operands", MD); + + // Check first operand. + Assert(MD->getOperand(0) != nullptr, "first operand should not be null", + MD); + Assert(isa<MDString>(MD->getOperand(0)), + "expected string with name of the !prof annotation", MD); + MDString *MDS = cast<MDString>(MD->getOperand(0)); + StringRef ProfName = MDS->getString(); + Assert(ProfName.equals("function_entry_count"), + "first operand should be 'function_entry_count'", MD); + + // Check second operand. + Assert(MD->getOperand(1) != nullptr, "second operand should not be null", + MD); + Assert(isa<ConstantAsMetadata>(MD->getOperand(1)), + "expected integer argument to function_entry_count", MD); + } } } @@ -1026,9 +1493,9 @@ void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) { if (CE->getOpcode() != Instruction::BitCast) return; - Assert1(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0), - CE->getType()), - "Invalid bitcast", CE); + Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0), + CE->getType()), + "Invalid bitcast", CE); } bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { @@ -1045,6 +1512,159 @@ bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { return false; } +/// \brief Verify that statepoint intrinsic is well formed. +void Verifier::VerifyStatepoint(ImmutableCallSite CS) { + assert(CS.getCalledFunction() && + CS.getCalledFunction()->getIntrinsicID() == + Intrinsic::experimental_gc_statepoint); + + const Instruction &CI = *CS.getInstruction(); + + Assert(!CS.doesNotAccessMemory() && !CS.onlyReadsMemory(), + "gc.statepoint must read and write memory to preserve " + "reordering restrictions required by safepoint semantics", + &CI); + + const Value *IDV = CS.getArgument(0); + Assert(isa<ConstantInt>(IDV), "gc.statepoint ID must be a constant integer", + &CI); + + const Value *NumPatchBytesV = CS.getArgument(1); + Assert(isa<ConstantInt>(NumPatchBytesV), + "gc.statepoint number of patchable bytes must be a constant integer", + &CI); + const int64_t NumPatchBytes = + cast<ConstantInt>(NumPatchBytesV)->getSExtValue(); + assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!"); + Assert(NumPatchBytes >= 0, "gc.statepoint number of patchable bytes must be " + "positive", + &CI); + + const Value *Target = CS.getArgument(2); + const PointerType *PT = dyn_cast<PointerType>(Target->getType()); + Assert(PT && PT->getElementType()->isFunctionTy(), + "gc.statepoint callee must be of function pointer type", &CI, Target); + FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); + + if (NumPatchBytes) + Assert(isa<ConstantPointerNull>(Target->stripPointerCasts()), + "gc.statepoint must have null as call target if number of patchable " + "bytes is non zero", + &CI); + + const Value *NumCallArgsV = CS.getArgument(3); + Assert(isa<ConstantInt>(NumCallArgsV), + "gc.statepoint number of arguments to underlying call " + "must be constant integer", + &CI); + const int NumCallArgs = cast<ConstantInt>(NumCallArgsV)->getZExtValue(); + Assert(NumCallArgs >= 0, + "gc.statepoint number of arguments to underlying call " + "must be positive", + &CI); + const int NumParams = (int)TargetFuncType->getNumParams(); + if (TargetFuncType->isVarArg()) { + Assert(NumCallArgs >= NumParams, + "gc.statepoint mismatch in number of vararg call args", &CI); + + // TODO: Remove this limitation + Assert(TargetFuncType->getReturnType()->isVoidTy(), + "gc.statepoint doesn't support wrapping non-void " + "vararg functions yet", + &CI); + } else + Assert(NumCallArgs == NumParams, + "gc.statepoint mismatch in number of call args", &CI); + + const Value *FlagsV = CS.getArgument(4); + Assert(isa<ConstantInt>(FlagsV), + "gc.statepoint flags must be constant integer", &CI); + const uint64_t Flags = cast<ConstantInt>(FlagsV)->getZExtValue(); + Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0, + "unknown flag used in gc.statepoint flags argument", &CI); + + // Verify that the types of the call parameter arguments match + // the type of the wrapped callee. + for (int i = 0; i < NumParams; i++) { + Type *ParamType = TargetFuncType->getParamType(i); + Type *ArgType = CS.getArgument(5 + i)->getType(); + Assert(ArgType == ParamType, + "gc.statepoint call argument does not match wrapped " + "function type", + &CI); + } + + const int EndCallArgsInx = 4 + NumCallArgs; + + const Value *NumTransitionArgsV = CS.getArgument(EndCallArgsInx+1); + Assert(isa<ConstantInt>(NumTransitionArgsV), + "gc.statepoint number of transition arguments " + "must be constant integer", + &CI); + const int NumTransitionArgs = + cast<ConstantInt>(NumTransitionArgsV)->getZExtValue(); + Assert(NumTransitionArgs >= 0, + "gc.statepoint number of transition arguments must be positive", &CI); + const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; + + const Value *NumDeoptArgsV = CS.getArgument(EndTransitionArgsInx+1); + Assert(isa<ConstantInt>(NumDeoptArgsV), + "gc.statepoint number of deoptimization arguments " + "must be constant integer", + &CI); + const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); + Assert(NumDeoptArgs >= 0, "gc.statepoint number of deoptimization arguments " + "must be positive", + &CI); + + const int ExpectedNumArgs = + 7 + NumCallArgs + NumTransitionArgs + NumDeoptArgs; + Assert(ExpectedNumArgs <= (int)CS.arg_size(), + "gc.statepoint too few arguments according to length fields", &CI); + + // Check that the only uses of this gc.statepoint are gc.result or + // gc.relocate calls which are tied to this statepoint and thus part + // of the same statepoint sequence + for (const User *U : CI.users()) { + const CallInst *Call = dyn_cast<const CallInst>(U); + Assert(Call, "illegal use of statepoint token", &CI, U); + if (!Call) continue; + Assert(isGCRelocate(Call) || isGCResult(Call), + "gc.result or gc.relocate are the only value uses" + "of a gc.statepoint", + &CI, U); + if (isGCResult(Call)) { + Assert(Call->getArgOperand(0) == &CI, + "gc.result connected to wrong gc.statepoint", &CI, Call); + } else if (isGCRelocate(Call)) { + Assert(Call->getArgOperand(0) == &CI, + "gc.relocate connected to wrong gc.statepoint", &CI, Call); + } + } + + // Note: It is legal for a single derived pointer to be listed multiple + // times. It's non-optimal, but it is legal. It can also happen after + // insertion if we strip a bitcast away. + // Note: It is really tempting to check that each base is relocated and + // that a derived pointer is never reused as a base pointer. This turns + // out to be problematic since optimizations run after safepoint insertion + // can recognize equality properties that the insertion logic doesn't know + // about. See example statepoint.ll in the verifier subdirectory +} + +void Verifier::verifyFrameRecoverIndices() { + for (auto &Counts : FrameEscapeInfo) { + Function *F = Counts.first; + unsigned EscapedObjectCount = Counts.second.first; + unsigned MaxRecoveredIndex = Counts.second.second; + Assert(MaxRecoveredIndex <= EscapedObjectCount, + "all indices passed to llvm.framerecover must be less than the " + "number of arguments passed ot llvm.frameescape in the parent " + "function", + F); + } +} + // visitFunction - Verify that a function is ok. // void Verifier::visitFunction(const Function &F) { @@ -1052,25 +1672,24 @@ void Verifier::visitFunction(const Function &F) { FunctionType *FT = F.getFunctionType(); unsigned NumArgs = F.arg_size(); - Assert1(Context == &F.getContext(), - "Function context does not match Module context!", &F); + Assert(Context == &F.getContext(), + "Function context does not match Module context!", &F); - Assert1(!F.hasCommonLinkage(), "Functions may not have common linkage", &F); - Assert2(FT->getNumParams() == NumArgs, - "# formal arguments must match # of arguments for function type!", - &F, FT); - Assert1(F.getReturnType()->isFirstClassType() || - F.getReturnType()->isVoidTy() || - F.getReturnType()->isStructTy(), - "Functions cannot return aggregate values!", &F); + Assert(!F.hasCommonLinkage(), "Functions may not have common linkage", &F); + Assert(FT->getNumParams() == NumArgs, + "# formal arguments must match # of arguments for function type!", &F, + FT); + Assert(F.getReturnType()->isFirstClassType() || + F.getReturnType()->isVoidTy() || F.getReturnType()->isStructTy(), + "Functions cannot return aggregate values!", &F); - Assert1(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(), - "Invalid struct return type!", &F); + Assert(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(), + "Invalid struct return type!", &F); AttributeSet Attrs = F.getAttributes(); - Assert1(VerifyAttributeCount(Attrs, FT->getNumParams()), - "Attribute after last parameter!", &F); + Assert(VerifyAttributeCount(Attrs, FT->getNumParams()), + "Attribute after last parameter!", &F); // Check function attributes. VerifyFunctionAttrs(FT, Attrs, &F); @@ -1078,9 +1697,8 @@ void Verifier::visitFunction(const Function &F) { // On function declarations/definitions, we do not support the builtin // attribute. We do not check this in VerifyFunctionAttrs since that is // checking for Attributes that can/can not ever be on functions. - Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex, - Attribute::Builtin), - "Attribute 'builtin' can only be applied to a callsite.", &F); + Assert(!Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::Builtin), + "Attribute 'builtin' can only be applied to a callsite.", &F); // Check that this function meets the restrictions on this calling convention. // Sometimes varargs is used for perfectly forwarding thunks, so some of these @@ -1094,8 +1712,9 @@ void Verifier::visitFunction(const Function &F) { case CallingConv::Intel_OCL_BI: case CallingConv::PTX_Kernel: case CallingConv::PTX_Device: - Assert1(!F.isVarArg(), "Calling convention does not support varargs or " - "perfect forwarding!", &F); + Assert(!F.isVarArg(), "Calling convention does not support varargs or " + "perfect forwarding!", + &F); break; } @@ -1106,36 +1725,52 @@ void Verifier::visitFunction(const Function &F) { unsigned i = 0; for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I, ++i) { - Assert2(I->getType() == FT->getParamType(i), - "Argument value does not match function argument type!", - I, FT->getParamType(i)); - Assert1(I->getType()->isFirstClassType(), - "Function arguments must have first-class types!", I); + Assert(I->getType() == FT->getParamType(i), + "Argument value does not match function argument type!", I, + FT->getParamType(i)); + Assert(I->getType()->isFirstClassType(), + "Function arguments must have first-class types!", I); if (!isLLVMdotName) - Assert2(!I->getType()->isMetadataTy(), - "Function takes metadata but isn't an intrinsic", I, &F); + Assert(!I->getType()->isMetadataTy(), + "Function takes metadata but isn't an intrinsic", I, &F); } + // Get the function metadata attachments. + SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; + F.getAllMetadata(MDs); + assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync"); + VerifyFunctionMetadata(MDs); + if (F.isMaterializable()) { // Function has a body somewhere we can't see. + Assert(MDs.empty(), "unmaterialized function cannot have metadata", &F, + MDs.empty() ? nullptr : MDs.front().second); } else if (F.isDeclaration()) { - Assert1(F.hasExternalLinkage() || F.hasExternalWeakLinkage(), - "invalid linkage type for function declaration", &F); + Assert(F.hasExternalLinkage() || F.hasExternalWeakLinkage(), + "invalid linkage type for function declaration", &F); + Assert(MDs.empty(), "function without a body cannot have metadata", &F, + MDs.empty() ? nullptr : MDs.front().second); + Assert(!F.hasPersonalityFn(), + "Function declaration shouldn't have a personality routine", &F); } else { // Verify that this function (which has a body) is not named "llvm.*". It // is not legal to define intrinsics. - Assert1(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F); + Assert(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F); // Check the entry node const BasicBlock *Entry = &F.getEntryBlock(); - Assert1(pred_empty(Entry), - "Entry block to function must not have predecessors!", Entry); + Assert(pred_empty(Entry), + "Entry block to function must not have predecessors!", Entry); // The address of the entry block cannot be taken, unless it is dead. if (Entry->hasAddressTaken()) { - Assert1(!BlockAddress::lookup(Entry)->isConstantUsed(), - "blockaddress may not be used with the entry block!", Entry); + Assert(!BlockAddress::lookup(Entry)->isConstantUsed(), + "blockaddress may not be used with the entry block!", Entry); } + + // Visit metadata attachments. + for (const auto &I : MDs) + visitMDNode(*I.second); } // If this function is actually an intrinsic, verify that it is only used in @@ -1143,13 +1778,13 @@ void Verifier::visitFunction(const Function &F) { if (F.getIntrinsicID()) { const User *U; if (F.hasAddressTaken(&U)) - Assert1(0, "Invalid user of intrinsic instruction!", U); + Assert(0, "Invalid user of intrinsic instruction!", U); } - Assert1(!F.hasDLLImportStorageClass() || - (F.isDeclaration() && F.hasExternalLinkage()) || - F.hasAvailableExternallyLinkage(), - "Function is marked as dllimport, but not external.", &F); + Assert(!F.hasDLLImportStorageClass() || + (F.isDeclaration() && F.hasExternalLinkage()) || + F.hasAvailableExternallyLinkage(), + "Function is marked as dllimport, but not external.", &F); } // verifyBasicBlock - Verify that a basic block is well formed... @@ -1158,7 +1793,7 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { InstsInThisBlock.clear(); // Ensure that basic blocks have terminators! - Assert1(BB.getTerminator(), "Basic Block does not have terminator!", &BB); + Assert(BB.getTerminator(), "Basic Block does not have terminator!", &BB); // Check constraints that this basic block imposes on all of the PHI nodes in // it. @@ -1169,12 +1804,14 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { PHINode *PN; for (BasicBlock::iterator I = BB.begin(); (PN = dyn_cast<PHINode>(I));++I) { // Ensure that PHI nodes have at least one entry! - Assert1(PN->getNumIncomingValues() != 0, - "PHI nodes must have at least one entry. If the block is dead, " - "the PHI should be removed!", PN); - Assert1(PN->getNumIncomingValues() == Preds.size(), - "PHINode should have one entry for each predecessor of its " - "parent basic block!", PN); + Assert(PN->getNumIncomingValues() != 0, + "PHI nodes must have at least one entry. If the block is dead, " + "the PHI should be removed!", + PN); + Assert(PN->getNumIncomingValues() == Preds.size(), + "PHINode should have one entry for each predecessor of its " + "parent basic block!", + PN); // Get and sort all incoming values in the PHI node... Values.clear(); @@ -1189,17 +1826,17 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { // particular basic block in this PHI node, that the incoming values are // all identical. // - Assert4(i == 0 || Values[i].first != Values[i-1].first || - Values[i].second == Values[i-1].second, - "PHI node has multiple entries for the same basic block with " - "different incoming values!", PN, Values[i].first, - Values[i].second, Values[i-1].second); + Assert(i == 0 || Values[i].first != Values[i - 1].first || + Values[i].second == Values[i - 1].second, + "PHI node has multiple entries for the same basic block with " + "different incoming values!", + PN, Values[i].first, Values[i].second, Values[i - 1].second); // Check to make sure that the predecessors and PHI node entries are // matched up. - Assert3(Values[i].first == Preds[i], - "PHI node entries do not match predecessors!", PN, - Values[i].first, Preds[i]); + Assert(Values[i].first == Preds[i], + "PHI node entries do not match predecessors!", PN, + Values[i].first, Preds[i]); } } } @@ -1213,15 +1850,15 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { void Verifier::visitTerminatorInst(TerminatorInst &I) { // Ensure that terminators only exist at the end of the basic block. - Assert1(&I == I.getParent()->getTerminator(), - "Terminator found in the middle of a basic block!", I.getParent()); + Assert(&I == I.getParent()->getTerminator(), + "Terminator found in the middle of a basic block!", I.getParent()); visitInstruction(I); } void Verifier::visitBranchInst(BranchInst &BI) { if (BI.isConditional()) { - Assert2(BI.getCondition()->getType()->isIntegerTy(1), - "Branch condition is not 'i1' type!", &BI, BI.getCondition()); + Assert(BI.getCondition()->getType()->isIntegerTy(1), + "Branch condition is not 'i1' type!", &BI, BI.getCondition()); } visitTerminatorInst(BI); } @@ -1230,13 +1867,15 @@ void Verifier::visitReturnInst(ReturnInst &RI) { Function *F = RI.getParent()->getParent(); unsigned N = RI.getNumOperands(); if (F->getReturnType()->isVoidTy()) - Assert2(N == 0, - "Found return instr that returns non-void in Function of void " - "return type!", &RI, F->getReturnType()); + Assert(N == 0, + "Found return instr that returns non-void in Function of void " + "return type!", + &RI, F->getReturnType()); else - Assert2(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(), - "Function return type does not match operand " - "type of return inst!", &RI, F->getReturnType()); + Assert(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(), + "Function return type does not match operand " + "type of return inst!", + &RI, F->getReturnType()); // Check to make sure that the return value has necessary properties for // terminators... @@ -1249,32 +1888,32 @@ void Verifier::visitSwitchInst(SwitchInst &SI) { Type *SwitchTy = SI.getCondition()->getType(); SmallPtrSet<ConstantInt*, 32> Constants; 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()).second, - "Duplicate integer as switch case", &SI, i.getCaseValue()); + Assert(i.getCaseValue()->getType() == SwitchTy, + "Switch constants must all be same type as switch value!", &SI); + Assert(Constants.insert(i.getCaseValue()).second, + "Duplicate integer as switch case", &SI, i.getCaseValue()); } visitTerminatorInst(SI); } void Verifier::visitIndirectBrInst(IndirectBrInst &BI) { - Assert1(BI.getAddress()->getType()->isPointerTy(), - "Indirectbr operand must have pointer type!", &BI); + Assert(BI.getAddress()->getType()->isPointerTy(), + "Indirectbr operand must have pointer type!", &BI); for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i) - Assert1(BI.getDestination(i)->getType()->isLabelTy(), - "Indirectbr destinations must all have pointer type!", &BI); + Assert(BI.getDestination(i)->getType()->isLabelTy(), + "Indirectbr destinations must all have pointer type!", &BI); visitTerminatorInst(BI); } void Verifier::visitSelectInst(SelectInst &SI) { - Assert1(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1), - SI.getOperand(2)), - "Invalid operands for select instruction!", &SI); + Assert(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1), + SI.getOperand(2)), + "Invalid operands for select instruction!", &SI); - Assert1(SI.getTrueValue()->getType() == SI.getType(), - "Select values must have same type as select instruction!", &SI); + Assert(SI.getTrueValue()->getType() == SI.getType(), + "Select values must have same type as select instruction!", &SI); visitInstruction(SI); } @@ -1282,7 +1921,7 @@ void Verifier::visitSelectInst(SelectInst &SI) { /// a pass, if any exist, it's an error. /// void Verifier::visitUserOp1(Instruction &I) { - Assert1(0, "User-defined operators should not live outside of a pass!", &I); + Assert(0, "User-defined operators should not live outside of a pass!", &I); } void Verifier::visitTruncInst(TruncInst &I) { @@ -1294,11 +1933,11 @@ void Verifier::visitTruncInst(TruncInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I); - Assert1(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "trunc source and destination must both be a vector or neither", &I); - Assert1(SrcBitSize > DestBitSize,"DestTy too big for Trunc", &I); + Assert(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I); + Assert(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), + "trunc source and destination must both be a vector or neither", &I); + Assert(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I); visitInstruction(I); } @@ -1309,14 +1948,14 @@ void Verifier::visitZExtInst(ZExtInst &I) { Type *DestTy = I.getType(); // Get the size of the types in bits, we'll need this later - Assert1(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I); - Assert1(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "zext source and destination must both be a vector or neither", &I); + Assert(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I); + Assert(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), + "zext source and destination must both be a vector or neither", &I); unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcBitSize < DestBitSize,"Type too small for ZExt", &I); + Assert(SrcBitSize < DestBitSize, "Type too small for ZExt", &I); visitInstruction(I); } @@ -1330,11 +1969,11 @@ void Verifier::visitSExtInst(SExtInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I); - Assert1(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "sext source and destination must both be a vector or neither", &I); - Assert1(SrcBitSize < DestBitSize,"Type too small for SExt", &I); + Assert(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I); + Assert(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), + "sext source and destination must both be a vector or neither", &I); + Assert(SrcBitSize < DestBitSize, "Type too small for SExt", &I); visitInstruction(I); } @@ -1347,11 +1986,11 @@ void Verifier::visitFPTruncInst(FPTruncInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isFPOrFPVectorTy(),"FPTrunc only operates on FP", &I); - Assert1(DestTy->isFPOrFPVectorTy(),"FPTrunc only produces an FP", &I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "fptrunc source and destination must both be a vector or neither",&I); - Assert1(SrcBitSize > DestBitSize,"DestTy too big for FPTrunc", &I); + Assert(SrcTy->isFPOrFPVectorTy(), "FPTrunc only operates on FP", &I); + Assert(DestTy->isFPOrFPVectorTy(), "FPTrunc only produces an FP", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), + "fptrunc source and destination must both be a vector or neither", &I); + Assert(SrcBitSize > DestBitSize, "DestTy too big for FPTrunc", &I); visitInstruction(I); } @@ -1365,11 +2004,11 @@ void Verifier::visitFPExtInst(FPExtInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isFPOrFPVectorTy(),"FPExt only operates on FP", &I); - Assert1(DestTy->isFPOrFPVectorTy(),"FPExt only produces an FP", &I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "fpext source and destination must both be a vector or neither", &I); - Assert1(SrcBitSize < DestBitSize,"DestTy too small for FPExt", &I); + Assert(SrcTy->isFPOrFPVectorTy(), "FPExt only operates on FP", &I); + Assert(DestTy->isFPOrFPVectorTy(), "FPExt only produces an FP", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), + "fpext source and destination must both be a vector or neither", &I); + Assert(SrcBitSize < DestBitSize, "DestTy too small for FPExt", &I); visitInstruction(I); } @@ -1382,17 +2021,17 @@ void Verifier::visitUIToFPInst(UIToFPInst &I) { bool SrcVec = SrcTy->isVectorTy(); bool DstVec = DestTy->isVectorTy(); - Assert1(SrcVec == DstVec, - "UIToFP source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isIntOrIntVectorTy(), - "UIToFP source must be integer or integer vector", &I); - Assert1(DestTy->isFPOrFPVectorTy(), - "UIToFP result must be FP or FP vector", &I); + Assert(SrcVec == DstVec, + "UIToFP source and dest must both be vector or scalar", &I); + Assert(SrcTy->isIntOrIntVectorTy(), + "UIToFP source must be integer or integer vector", &I); + Assert(DestTy->isFPOrFPVectorTy(), "UIToFP result must be FP or FP vector", + &I); if (SrcVec && DstVec) - Assert1(cast<VectorType>(SrcTy)->getNumElements() == - cast<VectorType>(DestTy)->getNumElements(), - "UIToFP source and dest vector length mismatch", &I); + Assert(cast<VectorType>(SrcTy)->getNumElements() == + cast<VectorType>(DestTy)->getNumElements(), + "UIToFP source and dest vector length mismatch", &I); visitInstruction(I); } @@ -1405,17 +2044,17 @@ void Verifier::visitSIToFPInst(SIToFPInst &I) { bool SrcVec = SrcTy->isVectorTy(); bool DstVec = DestTy->isVectorTy(); - Assert1(SrcVec == DstVec, - "SIToFP source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isIntOrIntVectorTy(), - "SIToFP source must be integer or integer vector", &I); - Assert1(DestTy->isFPOrFPVectorTy(), - "SIToFP result must be FP or FP vector", &I); + Assert(SrcVec == DstVec, + "SIToFP source and dest must both be vector or scalar", &I); + Assert(SrcTy->isIntOrIntVectorTy(), + "SIToFP source must be integer or integer vector", &I); + Assert(DestTy->isFPOrFPVectorTy(), "SIToFP result must be FP or FP vector", + &I); if (SrcVec && DstVec) - Assert1(cast<VectorType>(SrcTy)->getNumElements() == - cast<VectorType>(DestTy)->getNumElements(), - "SIToFP source and dest vector length mismatch", &I); + Assert(cast<VectorType>(SrcTy)->getNumElements() == + cast<VectorType>(DestTy)->getNumElements(), + "SIToFP source and dest vector length mismatch", &I); visitInstruction(I); } @@ -1428,17 +2067,17 @@ void Verifier::visitFPToUIInst(FPToUIInst &I) { bool SrcVec = SrcTy->isVectorTy(); bool DstVec = DestTy->isVectorTy(); - Assert1(SrcVec == DstVec, - "FPToUI source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector", - &I); - Assert1(DestTy->isIntOrIntVectorTy(), - "FPToUI result must be integer or integer vector", &I); + Assert(SrcVec == DstVec, + "FPToUI source and dest must both be vector or scalar", &I); + Assert(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector", + &I); + Assert(DestTy->isIntOrIntVectorTy(), + "FPToUI result must be integer or integer vector", &I); if (SrcVec && DstVec) - Assert1(cast<VectorType>(SrcTy)->getNumElements() == - cast<VectorType>(DestTy)->getNumElements(), - "FPToUI source and dest vector length mismatch", &I); + Assert(cast<VectorType>(SrcTy)->getNumElements() == + cast<VectorType>(DestTy)->getNumElements(), + "FPToUI source and dest vector length mismatch", &I); visitInstruction(I); } @@ -1451,17 +2090,17 @@ void Verifier::visitFPToSIInst(FPToSIInst &I) { bool SrcVec = SrcTy->isVectorTy(); bool DstVec = DestTy->isVectorTy(); - Assert1(SrcVec == DstVec, - "FPToSI source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isFPOrFPVectorTy(), - "FPToSI source must be FP or FP vector", &I); - Assert1(DestTy->isIntOrIntVectorTy(), - "FPToSI result must be integer or integer vector", &I); + Assert(SrcVec == DstVec, + "FPToSI source and dest must both be vector or scalar", &I); + Assert(SrcTy->isFPOrFPVectorTy(), "FPToSI source must be FP or FP vector", + &I); + Assert(DestTy->isIntOrIntVectorTy(), + "FPToSI result must be integer or integer vector", &I); if (SrcVec && DstVec) - Assert1(cast<VectorType>(SrcTy)->getNumElements() == - cast<VectorType>(DestTy)->getNumElements(), - "FPToSI source and dest vector length mismatch", &I); + Assert(cast<VectorType>(SrcTy)->getNumElements() == + cast<VectorType>(DestTy)->getNumElements(), + "FPToSI source and dest vector length mismatch", &I); visitInstruction(I); } @@ -1471,18 +2110,18 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) { Type *SrcTy = I.getOperand(0)->getType(); Type *DestTy = I.getType(); - Assert1(SrcTy->getScalarType()->isPointerTy(), - "PtrToInt source must be pointer", &I); - Assert1(DestTy->getScalarType()->isIntegerTy(), - "PtrToInt result must be integral", &I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "PtrToInt type mismatch", &I); + Assert(SrcTy->getScalarType()->isPointerTy(), + "PtrToInt source must be pointer", &I); + Assert(DestTy->getScalarType()->isIntegerTy(), + "PtrToInt result must be integral", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch", + &I); if (SrcTy->isVectorTy()) { VectorType *VSrc = dyn_cast<VectorType>(SrcTy); VectorType *VDest = dyn_cast<VectorType>(DestTy); - Assert1(VSrc->getNumElements() == VDest->getNumElements(), - "PtrToInt Vector width mismatch", &I); + Assert(VSrc->getNumElements() == VDest->getNumElements(), + "PtrToInt Vector width mismatch", &I); } visitInstruction(I); @@ -1493,23 +2132,23 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) { Type *SrcTy = I.getOperand(0)->getType(); Type *DestTy = I.getType(); - Assert1(SrcTy->getScalarType()->isIntegerTy(), - "IntToPtr source must be an integral", &I); - Assert1(DestTy->getScalarType()->isPointerTy(), - "IntToPtr result must be a pointer",&I); - Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), - "IntToPtr type mismatch", &I); + Assert(SrcTy->getScalarType()->isIntegerTy(), + "IntToPtr source must be an integral", &I); + Assert(DestTy->getScalarType()->isPointerTy(), + "IntToPtr result must be a pointer", &I); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch", + &I); if (SrcTy->isVectorTy()) { VectorType *VSrc = dyn_cast<VectorType>(SrcTy); VectorType *VDest = dyn_cast<VectorType>(DestTy); - Assert1(VSrc->getNumElements() == VDest->getNumElements(), - "IntToPtr Vector width mismatch", &I); + Assert(VSrc->getNumElements() == VDest->getNumElements(), + "IntToPtr Vector width mismatch", &I); } visitInstruction(I); } void Verifier::visitBitCastInst(BitCastInst &I) { - Assert1( + Assert( CastInst::castIsValid(Instruction::BitCast, I.getOperand(0), I.getType()), "Invalid bitcast", &I); visitInstruction(I); @@ -1519,15 +2158,15 @@ void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { Type *SrcTy = I.getOperand(0)->getType(); Type *DestTy = I.getType(); - Assert1(SrcTy->isPtrOrPtrVectorTy(), - "AddrSpaceCast source must be a pointer", &I); - Assert1(DestTy->isPtrOrPtrVectorTy(), - "AddrSpaceCast result must be a pointer", &I); - Assert1(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(), - "AddrSpaceCast must be between different address spaces", &I); + Assert(SrcTy->isPtrOrPtrVectorTy(), "AddrSpaceCast source must be a pointer", + &I); + Assert(DestTy->isPtrOrPtrVectorTy(), "AddrSpaceCast result must be a pointer", + &I); + Assert(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(), + "AddrSpaceCast must be between different address spaces", &I); if (SrcTy->isVectorTy()) - Assert1(SrcTy->getVectorNumElements() == DestTy->getVectorNumElements(), - "AddrSpaceCast vector pointer number of elements mismatch", &I); + Assert(SrcTy->getVectorNumElements() == DestTy->getVectorNumElements(), + "AddrSpaceCast vector pointer number of elements mismatch", &I); visitInstruction(I); } @@ -1538,16 +2177,15 @@ void Verifier::visitPHINode(PHINode &PN) { // This can be tested by checking whether the instruction before this is // either nonexistent (because this is begin()) or is a PHI node. If not, // then there is some other instruction before a PHI. - Assert2(&PN == &PN.getParent()->front() || - isa<PHINode>(--BasicBlock::iterator(&PN)), - "PHI nodes not grouped at top of basic block!", - &PN, PN.getParent()); + Assert(&PN == &PN.getParent()->front() || + isa<PHINode>(--BasicBlock::iterator(&PN)), + "PHI nodes not grouped at top of basic block!", &PN, PN.getParent()); // Check that all of the values of the PHI node have the same type as the // result, and that the incoming blocks are really basic blocks. - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { - Assert1(PN.getType() == PN.getIncomingValue(i)->getType(), - "PHI node operands are not the same type as the result!", &PN); + for (Value *IncValue : PN.incoming_values()) { + Assert(PN.getType() == IncValue->getType(), + "PHI node operands are not the same type as the result!", &PN); } // All other PHI node constraints are checked in the visitBasicBlock method. @@ -1558,32 +2196,36 @@ void Verifier::visitPHINode(PHINode &PN) { void Verifier::VerifyCallSite(CallSite CS) { Instruction *I = CS.getInstruction(); - Assert1(CS.getCalledValue()->getType()->isPointerTy(), - "Called function must be a pointer!", I); + Assert(CS.getCalledValue()->getType()->isPointerTy(), + "Called function must be a pointer!", I); PointerType *FPTy = cast<PointerType>(CS.getCalledValue()->getType()); - Assert1(FPTy->getElementType()->isFunctionTy(), - "Called function is not pointer to function type!", I); - FunctionType *FTy = cast<FunctionType>(FPTy->getElementType()); + Assert(FPTy->getElementType()->isFunctionTy(), + "Called function is not pointer to function type!", I); + + Assert(FPTy->getElementType() == CS.getFunctionType(), + "Called function is not the same type as the call!", I); + + FunctionType *FTy = CS.getFunctionType(); // Verify that the correct number of arguments are being passed if (FTy->isVarArg()) - Assert1(CS.arg_size() >= FTy->getNumParams(), - "Called function requires more parameters than were provided!",I); + Assert(CS.arg_size() >= FTy->getNumParams(), + "Called function requires more parameters than were provided!", I); else - Assert1(CS.arg_size() == FTy->getNumParams(), - "Incorrect number of arguments passed to called function!", I); + Assert(CS.arg_size() == FTy->getNumParams(), + "Incorrect number of arguments passed to called function!", I); // Verify that all arguments to the call match the function type. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) - Assert3(CS.getArgument(i)->getType() == FTy->getParamType(i), - "Call parameter type does not match function signature!", - CS.getArgument(i), FTy->getParamType(i), I); + Assert(CS.getArgument(i)->getType() == FTy->getParamType(i), + "Call parameter type does not match function signature!", + CS.getArgument(i), FTy->getParamType(i), I); AttributeSet Attrs = CS.getAttributes(); - Assert1(VerifyAttributeCount(Attrs, CS.arg_size()), - "Attribute after last parameter!", I); + Assert(VerifyAttributeCount(Attrs, CS.arg_size()), + "Attribute after last parameter!", I); // Verify call attributes. VerifyFunctionAttrs(FTy, Attrs, I); @@ -1594,8 +2236,8 @@ void Verifier::VerifyCallSite(CallSite CS) { if (CS.hasInAllocaArgument()) { Value *InAllocaArg = CS.getArgument(FTy->getNumParams() - 1); if (auto AI = dyn_cast<AllocaInst>(InAllocaArg->stripInBoundsOffsets())) - Assert2(AI->isUsedWithInAlloca(), - "inalloca argument for call has mismatched alloca", AI, I); + Assert(AI->isUsedWithInAlloca(), + "inalloca argument for call has mismatched alloca", AI, I); } if (FTy->isVarArg()) { @@ -1616,25 +2258,25 @@ void Verifier::VerifyCallSite(CallSite CS) { VerifyParameterAttrs(Attrs, Idx, Ty, false, I); if (Attrs.hasAttribute(Idx, Attribute::Nest)) { - Assert1(!SawNest, "More than one parameter has attribute nest!", I); + Assert(!SawNest, "More than one parameter has attribute nest!", I); SawNest = true; } if (Attrs.hasAttribute(Idx, Attribute::Returned)) { - Assert1(!SawReturned, "More than one parameter has attribute returned!", - I); - Assert1(Ty->canLosslesslyBitCastTo(FTy->getReturnType()), - "Incompatible argument and return types for 'returned' " - "attribute", I); + Assert(!SawReturned, "More than one parameter has attribute returned!", + I); + Assert(Ty->canLosslesslyBitCastTo(FTy->getReturnType()), + "Incompatible argument and return types for 'returned' " + "attribute", + I); SawReturned = true; } - Assert1(!Attrs.hasAttribute(Idx, Attribute::StructRet), - "Attribute 'sret' cannot be used for vararg call arguments!", I); + Assert(!Attrs.hasAttribute(Idx, Attribute::StructRet), + "Attribute 'sret' cannot be used for vararg call arguments!", I); if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) - Assert1(Idx == CS.arg_size(), "inalloca isn't on the last argument!", - I); + Assert(Idx == CS.arg_size(), "inalloca isn't on the last argument!", I); } } @@ -1643,8 +2285,8 @@ void Verifier::VerifyCallSite(CallSite CS) { !CS.getCalledFunction()->getName().startswith("llvm.")) { for (FunctionType::param_iterator PI = FTy->param_begin(), PE = FTy->param_end(); PI != PE; ++PI) - Assert1(!(*PI)->isMetadataTy(), - "Function has metadata parameter but isn't an intrinsic", I); + Assert(!(*PI)->isMetadataTy(), + "Function has metadata parameter but isn't an intrinsic", I); } visitInstruction(*I); @@ -1677,33 +2319,29 @@ static AttrBuilder getParameterABIAttributes(int I, AttributeSet Attrs) { } void Verifier::verifyMustTailCall(CallInst &CI) { - Assert1(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI); + Assert(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI); // - The caller and callee prototypes must match. Pointer types of // parameters or return types may differ in pointee type, but not // address space. Function *F = CI.getParent()->getParent(); - auto GetFnTy = [](Value *V) { - return cast<FunctionType>( - cast<PointerType>(V->getType())->getElementType()); - }; - FunctionType *CallerTy = GetFnTy(F); - FunctionType *CalleeTy = GetFnTy(CI.getCalledValue()); - Assert1(CallerTy->getNumParams() == CalleeTy->getNumParams(), - "cannot guarantee tail call due to mismatched parameter counts", &CI); - Assert1(CallerTy->isVarArg() == CalleeTy->isVarArg(), - "cannot guarantee tail call due to mismatched varargs", &CI); - Assert1(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()), - "cannot guarantee tail call due to mismatched return types", &CI); + FunctionType *CallerTy = F->getFunctionType(); + FunctionType *CalleeTy = CI.getFunctionType(); + Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(), + "cannot guarantee tail call due to mismatched parameter counts", &CI); + Assert(CallerTy->isVarArg() == CalleeTy->isVarArg(), + "cannot guarantee tail call due to mismatched varargs", &CI); + Assert(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()), + "cannot guarantee tail call due to mismatched return types", &CI); for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { - Assert1( + Assert( isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)), "cannot guarantee tail call due to mismatched parameter types", &CI); } // - The calling conventions of the caller and callee must match. - Assert1(F->getCallingConv() == CI.getCallingConv(), - "cannot guarantee tail call due to mismatched calling conv", &CI); + Assert(F->getCallingConv() == CI.getCallingConv(), + "cannot guarantee tail call due to mismatched calling conv", &CI); // - All ABI-impacting function attributes, such as sret, byval, inreg, // returned, and inalloca, must match. @@ -1712,9 +2350,10 @@ void Verifier::verifyMustTailCall(CallInst &CI) { for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs); AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs); - Assert2(CallerABIAttrs == CalleeABIAttrs, - "cannot guarantee tail call due to mismatched ABI impacting " - "function attributes", &CI, CI.getOperand(I)); + Assert(CallerABIAttrs == CalleeABIAttrs, + "cannot guarantee tail call due to mismatched ABI impacting " + "function attributes", + &CI, CI.getOperand(I)); } // - The call must immediately precede a :ref:`ret <i_ret>` instruction, @@ -1726,18 +2365,18 @@ void Verifier::verifyMustTailCall(CallInst &CI) { // Handle the optional bitcast. if (BitCastInst *BI = dyn_cast_or_null<BitCastInst>(Next)) { - Assert1(BI->getOperand(0) == RetVal, - "bitcast following musttail call must use the call", BI); + Assert(BI->getOperand(0) == RetVal, + "bitcast following musttail call must use the call", BI); RetVal = BI; Next = BI->getNextNode(); } // Check the return. ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next); - Assert1(Ret, "musttail call must be precede a ret with an optional bitcast", - &CI); - Assert1(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal, - "musttail call result must be returned", Ret); + Assert(Ret, "musttail call must be precede a ret with an optional bitcast", + &CI); + Assert(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal, + "musttail call result must be returned", Ret); } void Verifier::visitCallInst(CallInst &CI) { @@ -1747,7 +2386,7 @@ void Verifier::visitCallInst(CallInst &CI) { verifyMustTailCall(CI); if (Function *F = CI.getCalledFunction()) - if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) + if (Intrinsic::ID ID = F->getIntrinsicID()) visitIntrinsicFunctionCall(ID, CI); } @@ -1756,8 +2395,15 @@ void Verifier::visitInvokeInst(InvokeInst &II) { // Verify that there is a landingpad instruction as the first non-PHI // instruction of the 'unwind' destination. - Assert1(II.getUnwindDest()->isLandingPad(), - "The unwind destination does not have a landingpad instruction!",&II); + Assert(II.getUnwindDest()->isLandingPad(), + "The unwind destination does not have a landingpad instruction!", &II); + + if (Function *F = II.getCalledFunction()) + // TODO: Ideally we should use visitIntrinsicFunction here. But it uses + // CallInst as an input parameter. It not woth updating this whole + // function only to support statepoint verification. + if (F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint) + VerifyStatepoint(ImmutableCallSite(&II)); visitTerminatorInst(II); } @@ -1766,8 +2412,8 @@ void Verifier::visitInvokeInst(InvokeInst &II) { /// of the same type! /// void Verifier::visitBinaryOperator(BinaryOperator &B) { - Assert1(B.getOperand(0)->getType() == B.getOperand(1)->getType(), - "Both operands to a binary operator are not of the same type!", &B); + Assert(B.getOperand(0)->getType() == B.getOperand(1)->getType(), + "Both operands to a binary operator are not of the same type!", &B); switch (B.getOpcode()) { // Check that integer arithmetic operators are only used with @@ -1779,11 +2425,12 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { case Instruction::UDiv: case Instruction::SRem: case Instruction::URem: - Assert1(B.getType()->isIntOrIntVectorTy(), - "Integer arithmetic operators only work with integral types!", &B); - Assert1(B.getType() == B.getOperand(0)->getType(), - "Integer arithmetic operators must have same type " - "for operands and result!", &B); + Assert(B.getType()->isIntOrIntVectorTy(), + "Integer arithmetic operators only work with integral types!", &B); + Assert(B.getType() == B.getOperand(0)->getType(), + "Integer arithmetic operators must have same type " + "for operands and result!", + &B); break; // Check that floating-point arithmetic operators are only used with // floating-point operands. @@ -1792,30 +2439,32 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { case Instruction::FMul: case Instruction::FDiv: case Instruction::FRem: - Assert1(B.getType()->isFPOrFPVectorTy(), - "Floating-point arithmetic operators only work with " - "floating-point types!", &B); - Assert1(B.getType() == B.getOperand(0)->getType(), - "Floating-point arithmetic operators must have same type " - "for operands and result!", &B); + Assert(B.getType()->isFPOrFPVectorTy(), + "Floating-point arithmetic operators only work with " + "floating-point types!", + &B); + Assert(B.getType() == B.getOperand(0)->getType(), + "Floating-point arithmetic operators must have same type " + "for operands and result!", + &B); break; // Check that logical operators are only used with integral operands. case Instruction::And: case Instruction::Or: case Instruction::Xor: - Assert1(B.getType()->isIntOrIntVectorTy(), - "Logical operators only work with integral types!", &B); - Assert1(B.getType() == B.getOperand(0)->getType(), - "Logical operators must have same type for operands and result!", - &B); + Assert(B.getType()->isIntOrIntVectorTy(), + "Logical operators only work with integral types!", &B); + Assert(B.getType() == B.getOperand(0)->getType(), + "Logical operators must have same type for operands and result!", + &B); break; case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: - Assert1(B.getType()->isIntOrIntVectorTy(), - "Shifts only work with integral types!", &B); - Assert1(B.getType() == B.getOperand(0)->getType(), - "Shift return type must be same as operands!", &B); + Assert(B.getType()->isIntOrIntVectorTy(), + "Shifts only work with integral types!", &B); + Assert(B.getType() == B.getOperand(0)->getType(), + "Shift return type must be same as operands!", &B); break; default: llvm_unreachable("Unknown BinaryOperator opcode!"); @@ -1828,15 +2477,15 @@ void Verifier::visitICmpInst(ICmpInst &IC) { // Check that the operands are the same type Type *Op0Ty = IC.getOperand(0)->getType(); Type *Op1Ty = IC.getOperand(1)->getType(); - Assert1(Op0Ty == Op1Ty, - "Both operands to ICmp instruction are not of the same type!", &IC); + Assert(Op0Ty == Op1Ty, + "Both operands to ICmp instruction are not of the same type!", &IC); // Check that the operands are the right type - Assert1(Op0Ty->isIntOrIntVectorTy() || Op0Ty->getScalarType()->isPointerTy(), - "Invalid operand types for ICmp instruction", &IC); + Assert(Op0Ty->isIntOrIntVectorTy() || Op0Ty->getScalarType()->isPointerTy(), + "Invalid operand types for ICmp instruction", &IC); // Check that the predicate is valid. - Assert1(IC.getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE && - IC.getPredicate() <= CmpInst::LAST_ICMP_PREDICATE, - "Invalid predicate in ICmp instruction!", &IC); + Assert(IC.getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE && + IC.getPredicate() <= CmpInst::LAST_ICMP_PREDICATE, + "Invalid predicate in ICmp instruction!", &IC); visitInstruction(IC); } @@ -1845,72 +2494,70 @@ void Verifier::visitFCmpInst(FCmpInst &FC) { // Check that the operands are the same type Type *Op0Ty = FC.getOperand(0)->getType(); Type *Op1Ty = FC.getOperand(1)->getType(); - Assert1(Op0Ty == Op1Ty, - "Both operands to FCmp instruction are not of the same type!", &FC); + Assert(Op0Ty == Op1Ty, + "Both operands to FCmp instruction are not of the same type!", &FC); // Check that the operands are the right type - Assert1(Op0Ty->isFPOrFPVectorTy(), - "Invalid operand types for FCmp instruction", &FC); + Assert(Op0Ty->isFPOrFPVectorTy(), + "Invalid operand types for FCmp instruction", &FC); // Check that the predicate is valid. - Assert1(FC.getPredicate() >= CmpInst::FIRST_FCMP_PREDICATE && - FC.getPredicate() <= CmpInst::LAST_FCMP_PREDICATE, - "Invalid predicate in FCmp instruction!", &FC); + Assert(FC.getPredicate() >= CmpInst::FIRST_FCMP_PREDICATE && + FC.getPredicate() <= CmpInst::LAST_FCMP_PREDICATE, + "Invalid predicate in FCmp instruction!", &FC); visitInstruction(FC); } void Verifier::visitExtractElementInst(ExtractElementInst &EI) { - Assert1(ExtractElementInst::isValidOperands(EI.getOperand(0), - EI.getOperand(1)), - "Invalid extractelement operands!", &EI); + Assert( + ExtractElementInst::isValidOperands(EI.getOperand(0), EI.getOperand(1)), + "Invalid extractelement operands!", &EI); visitInstruction(EI); } void Verifier::visitInsertElementInst(InsertElementInst &IE) { - Assert1(InsertElementInst::isValidOperands(IE.getOperand(0), - IE.getOperand(1), - IE.getOperand(2)), - "Invalid insertelement operands!", &IE); + Assert(InsertElementInst::isValidOperands(IE.getOperand(0), IE.getOperand(1), + IE.getOperand(2)), + "Invalid insertelement operands!", &IE); visitInstruction(IE); } void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { - Assert1(ShuffleVectorInst::isValidOperands(SV.getOperand(0), SV.getOperand(1), - SV.getOperand(2)), - "Invalid shufflevector operands!", &SV); + Assert(ShuffleVectorInst::isValidOperands(SV.getOperand(0), SV.getOperand(1), + SV.getOperand(2)), + "Invalid shufflevector operands!", &SV); visitInstruction(SV); } void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { Type *TargetTy = GEP.getPointerOperandType()->getScalarType(); - Assert1(isa<PointerType>(TargetTy), - "GEP base pointer is not a vector or a vector of pointers", &GEP); - Assert1(cast<PointerType>(TargetTy)->getElementType()->isSized(), - "GEP into unsized type!", &GEP); - Assert1(GEP.getPointerOperandType()->isVectorTy() == - GEP.getType()->isVectorTy(), "Vector GEP must return a vector value", - &GEP); + Assert(isa<PointerType>(TargetTy), + "GEP base pointer is not a vector or a vector of pointers", &GEP); + Assert(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP); + Assert(GEP.getPointerOperandType()->isVectorTy() == + GEP.getType()->isVectorTy(), + "Vector GEP must return a vector value", &GEP); SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end()); Type *ElTy = - GetElementPtrInst::getIndexedType(GEP.getPointerOperandType(), Idxs); - Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP); + GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); + Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP); - Assert2(GEP.getType()->getScalarType()->isPointerTy() && - cast<PointerType>(GEP.getType()->getScalarType())->getElementType() - == ElTy, "GEP is not of right type for indices!", &GEP, ElTy); + Assert(GEP.getType()->getScalarType()->isPointerTy() && + GEP.getResultElementType() == ElTy, + "GEP is not of right type for indices!", &GEP, ElTy); if (GEP.getPointerOperandType()->isVectorTy()) { // Additional checks for vector GEPs. unsigned GepWidth = GEP.getPointerOperandType()->getVectorNumElements(); - Assert1(GepWidth == GEP.getType()->getVectorNumElements(), - "Vector GEP result width doesn't match operand's", &GEP); + Assert(GepWidth == GEP.getType()->getVectorNumElements(), + "Vector GEP result width doesn't match operand's", &GEP); for (unsigned i = 0, e = Idxs.size(); i != e; ++i) { Type *IndexTy = Idxs[i]->getType(); - Assert1(IndexTy->isVectorTy(), - "Vector GEP must have vector indices!", &GEP); + Assert(IndexTy->isVectorTy(), "Vector GEP must have vector indices!", + &GEP); unsigned IndexWidth = IndexTy->getVectorNumElements(); - Assert1(IndexWidth == GepWidth, "Invalid GEP index vector width", &GEP); + Assert(IndexWidth == GepWidth, "Invalid GEP index vector width", &GEP); } } visitInstruction(GEP); @@ -1927,34 +2574,33 @@ void Verifier::visitRangeMetadata(Instruction& I, "precondition violation"); unsigned NumOperands = Range->getNumOperands(); - Assert1(NumOperands % 2 == 0, "Unfinished range!", Range); + Assert(NumOperands % 2 == 0, "Unfinished range!", Range); unsigned NumRanges = NumOperands / 2; - Assert1(NumRanges >= 1, "It should have at least one range!", Range); - + Assert(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 = mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); - Assert1(Low, "The lower limit must be an integer!", Low); + Assert(Low, "The lower limit must be an integer!", Low); ConstantInt *High = mdconst::dyn_extract<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); - + Assert(High, "The upper limit must be an integer!", High); + Assert(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); + Assert(!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); + Assert(CurRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert(LowV.sgt(LastRange.getLower()), "Intervals are not in order", + Range); + Assert(!isContiguous(CurRange, LastRange), "Intervals are contiguous", + Range); } LastRange = ConstantRange(LowV, HighV); } @@ -1964,38 +2610,35 @@ void Verifier::visitRangeMetadata(Instruction& I, APInt FirstHigh = mdconst::dyn_extract<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); + Assert(FirstRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert(!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); + Assert(PTy, "Load operand must be a pointer.", &LI); + Type *ElTy = LI.getType(); + Assert(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); - Assert1(LI.getAlignment() != 0, - "Atomic load must specify explicit alignment", &LI); + Assert(LI.getOrdering() != Release && LI.getOrdering() != AcquireRelease, + "Load cannot have Release ordering", &LI); + Assert(LI.getAlignment() != 0, + "Atomic load must specify explicit alignment", &LI); if (!ElTy->isPointerTy()) { - Assert2(ElTy->isIntegerTy(), - "atomic load operand must have integer type!", - &LI, ElTy); + Assert(ElTy->isIntegerTy(), "atomic load operand must have integer type!", + &LI, ElTy); unsigned Size = ElTy->getPrimitiveSizeInBits(); - Assert2(Size >= 8 && !(Size & (Size - 1)), - "atomic load operand must be power-of-two byte-sized integer", - &LI, ElTy); + Assert(Size >= 8 && !(Size & (Size - 1)), + "atomic load operand must be power-of-two byte-sized integer", &LI, + ElTy); } } else { - Assert1(LI.getSynchScope() == CrossThread, - "Non-atomic load cannot have SynchronizationScope specified", &LI); + Assert(LI.getSynchScope() == CrossThread, + "Non-atomic load cannot have SynchronizationScope specified", &LI); } visitInstruction(LI); @@ -2003,30 +2646,28 @@ void Verifier::visitLoadInst(LoadInst &LI) { void Verifier::visitStoreInst(StoreInst &SI) { PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType()); - Assert1(PTy, "Store operand must be a pointer.", &SI); + Assert(PTy, "Store operand must be a pointer.", &SI); Type *ElTy = PTy->getElementType(); - 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); + Assert(ElTy == SI.getOperand(0)->getType(), + "Stored value type does not match pointer operand type!", &SI, ElTy); + Assert(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); - Assert1(SI.getAlignment() != 0, - "Atomic store must specify explicit alignment", &SI); + Assert(SI.getOrdering() != Acquire && SI.getOrdering() != AcquireRelease, + "Store cannot have Acquire ordering", &SI); + Assert(SI.getAlignment() != 0, + "Atomic store must specify explicit alignment", &SI); if (!ElTy->isPointerTy()) { - Assert2(ElTy->isIntegerTy(), - "atomic store operand must have integer type!", - &SI, ElTy); + Assert(ElTy->isIntegerTy(), + "atomic store operand must have integer type!", &SI, ElTy); unsigned Size = ElTy->getPrimitiveSizeInBits(); - Assert2(Size >= 8 && !(Size & (Size - 1)), - "atomic store operand must be power-of-two byte-sized integer", - &SI, ElTy); + Assert(Size >= 8 && !(Size & (Size - 1)), + "atomic store operand must be power-of-two byte-sized integer", + &SI, ElTy); } } else { - Assert1(SI.getSynchScope() == CrossThread, - "Non-atomic store cannot have SynchronizationScope specified", &SI); + Assert(SI.getSynchScope() == CrossThread, + "Non-atomic store cannot have SynchronizationScope specified", &SI); } visitInstruction(SI); } @@ -2034,15 +2675,15 @@ void Verifier::visitStoreInst(StoreInst &SI) { void Verifier::visitAllocaInst(AllocaInst &AI) { SmallPtrSet<const Type*, 4> Visited; PointerType *PTy = AI.getType(); - Assert1(PTy->getAddressSpace() == 0, - "Allocation instruction pointer not in the generic address space!", - &AI); - Assert1(PTy->getElementType()->isSized(&Visited), "Cannot allocate unsized type", - &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); + Assert(PTy->getAddressSpace() == 0, + "Allocation instruction pointer not in the generic address space!", + &AI); + Assert(AI.getAllocatedType()->isSized(&Visited), + "Cannot allocate unsized type", &AI); + Assert(AI.getArraySize()->getType()->isIntegerTy(), + "Alloca array size must have integer type", &AI); + Assert(AI.getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &AI); visitInstruction(AI); } @@ -2050,87 +2691,83 @@ void Verifier::visitAllocaInst(AllocaInst &AI) { void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { // FIXME: more conditions??? - Assert1(CXI.getSuccessOrdering() != NotAtomic, - "cmpxchg instructions must be atomic.", &CXI); - Assert1(CXI.getFailureOrdering() != NotAtomic, - "cmpxchg instructions must be atomic.", &CXI); - Assert1(CXI.getSuccessOrdering() != Unordered, - "cmpxchg instructions cannot be unordered.", &CXI); - Assert1(CXI.getFailureOrdering() != Unordered, - "cmpxchg instructions cannot be unordered.", &CXI); - Assert1(CXI.getSuccessOrdering() >= CXI.getFailureOrdering(), - "cmpxchg instructions be at least as constrained on success as fail", - &CXI); - Assert1(CXI.getFailureOrdering() != Release && - CXI.getFailureOrdering() != AcquireRelease, - "cmpxchg failure ordering cannot include release semantics", &CXI); + Assert(CXI.getSuccessOrdering() != NotAtomic, + "cmpxchg instructions must be atomic.", &CXI); + Assert(CXI.getFailureOrdering() != NotAtomic, + "cmpxchg instructions must be atomic.", &CXI); + Assert(CXI.getSuccessOrdering() != Unordered, + "cmpxchg instructions cannot be unordered.", &CXI); + Assert(CXI.getFailureOrdering() != Unordered, + "cmpxchg instructions cannot be unordered.", &CXI); + Assert(CXI.getSuccessOrdering() >= CXI.getFailureOrdering(), + "cmpxchg instructions be at least as constrained on success as fail", + &CXI); + Assert(CXI.getFailureOrdering() != Release && + CXI.getFailureOrdering() != AcquireRelease, + "cmpxchg failure ordering cannot include release semantics", &CXI); PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType()); - Assert1(PTy, "First cmpxchg operand must be a pointer.", &CXI); + Assert(PTy, "First cmpxchg operand must be a pointer.", &CXI); Type *ElTy = PTy->getElementType(); - Assert2(ElTy->isIntegerTy(), - "cmpxchg operand must have integer type!", - &CXI, ElTy); + Assert(ElTy->isIntegerTy(), "cmpxchg operand must have integer type!", &CXI, + ElTy); unsigned Size = ElTy->getPrimitiveSizeInBits(); - Assert2(Size >= 8 && !(Size & (Size - 1)), - "cmpxchg operand must be power-of-two byte-sized integer", - &CXI, ElTy); - Assert2(ElTy == CXI.getOperand(1)->getType(), - "Expected value type does not match pointer operand type!", - &CXI, ElTy); - Assert2(ElTy == CXI.getOperand(2)->getType(), - "Stored value type does not match pointer operand type!", - &CXI, ElTy); + Assert(Size >= 8 && !(Size & (Size - 1)), + "cmpxchg operand must be power-of-two byte-sized integer", &CXI, ElTy); + Assert(ElTy == CXI.getOperand(1)->getType(), + "Expected value type does not match pointer operand type!", &CXI, + ElTy); + Assert(ElTy == CXI.getOperand(2)->getType(), + "Stored value type does not match pointer operand type!", &CXI, ElTy); visitInstruction(CXI); } void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { - Assert1(RMWI.getOrdering() != NotAtomic, - "atomicrmw instructions must be atomic.", &RMWI); - Assert1(RMWI.getOrdering() != Unordered, - "atomicrmw instructions cannot be unordered.", &RMWI); + Assert(RMWI.getOrdering() != NotAtomic, + "atomicrmw instructions must be atomic.", &RMWI); + Assert(RMWI.getOrdering() != Unordered, + "atomicrmw instructions cannot be unordered.", &RMWI); PointerType *PTy = dyn_cast<PointerType>(RMWI.getOperand(0)->getType()); - Assert1(PTy, "First atomicrmw operand must be a pointer.", &RMWI); + Assert(PTy, "First atomicrmw operand must be a pointer.", &RMWI); Type *ElTy = PTy->getElementType(); - Assert2(ElTy->isIntegerTy(), - "atomicrmw operand must have integer type!", - &RMWI, ElTy); + Assert(ElTy->isIntegerTy(), "atomicrmw operand must have integer type!", + &RMWI, ElTy); unsigned Size = ElTy->getPrimitiveSizeInBits(); - Assert2(Size >= 8 && !(Size & (Size - 1)), - "atomicrmw operand must be power-of-two byte-sized integer", - &RMWI, ElTy); - Assert2(ElTy == RMWI.getOperand(1)->getType(), - "Argument value type does not match pointer operand type!", - &RMWI, ElTy); - Assert1(AtomicRMWInst::FIRST_BINOP <= RMWI.getOperation() && - RMWI.getOperation() <= AtomicRMWInst::LAST_BINOP, - "Invalid binary operation!", &RMWI); + Assert(Size >= 8 && !(Size & (Size - 1)), + "atomicrmw operand must be power-of-two byte-sized integer", &RMWI, + ElTy); + Assert(ElTy == RMWI.getOperand(1)->getType(), + "Argument value type does not match pointer operand type!", &RMWI, + ElTy); + Assert(AtomicRMWInst::FIRST_BINOP <= RMWI.getOperation() && + RMWI.getOperation() <= AtomicRMWInst::LAST_BINOP, + "Invalid binary operation!", &RMWI); visitInstruction(RMWI); } void Verifier::visitFenceInst(FenceInst &FI) { const AtomicOrdering Ordering = FI.getOrdering(); - Assert1(Ordering == Acquire || Ordering == Release || - Ordering == AcquireRelease || Ordering == SequentiallyConsistent, - "fence instructions may only have " - "acquire, release, acq_rel, or seq_cst ordering.", &FI); + Assert(Ordering == Acquire || Ordering == Release || + Ordering == AcquireRelease || Ordering == SequentiallyConsistent, + "fence instructions may only have " + "acquire, release, acq_rel, or seq_cst ordering.", + &FI); visitInstruction(FI); } void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { - Assert1(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(), - EVI.getIndices()) == - EVI.getType(), - "Invalid ExtractValueInst operands!", &EVI); + Assert(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(), + EVI.getIndices()) == EVI.getType(), + "Invalid ExtractValueInst operands!", &EVI); visitInstruction(EVI); } void Verifier::visitInsertValueInst(InsertValueInst &IVI) { - Assert1(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(), - IVI.getIndices()) == - IVI.getOperand(1)->getType(), - "Invalid InsertValueInst operands!", &IVI); + Assert(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(), + IVI.getIndices()) == + IVI.getOperand(1)->getType(), + "Invalid InsertValueInst operands!", &IVI); visitInstruction(IVI); } @@ -2140,43 +2777,38 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { // The landingpad instruction is ill-formed if it doesn't have any clauses and // isn't a cleanup. - Assert1(LPI.getNumClauses() > 0 || LPI.isCleanup(), - "LandingPadInst needs at least one clause or to be a cleanup.", &LPI); + Assert(LPI.getNumClauses() > 0 || LPI.isCleanup(), + "LandingPadInst needs at least one clause or to be a cleanup.", &LPI); // The landingpad instruction defines its parent as a landing pad block. The // landing pad block may be branched to only by the unwind edge of an invoke. for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { const InvokeInst *II = dyn_cast<InvokeInst>((*I)->getTerminator()); - Assert1(II && II->getUnwindDest() == BB && II->getNormalDest() != BB, - "Block containing LandingPadInst must be jumped to " - "only by the unwind edge of an invoke.", &LPI); + Assert(II && II->getUnwindDest() == BB && II->getNormalDest() != BB, + "Block containing LandingPadInst must be jumped to " + "only by the unwind edge of an invoke.", + &LPI); } + Function *F = LPI.getParent()->getParent(); + Assert(F->hasPersonalityFn(), + "LandingPadInst needs to be in a function with a personality.", &LPI); + // The landingpad instruction must be the first non-PHI instruction in the // block. - Assert1(LPI.getParent()->getLandingPadInst() == &LPI, - "LandingPadInst not the first non-PHI instruction in the block.", - &LPI); - - // The personality functions for all landingpad instructions within the same - // function should match. - if (PersonalityFn) - Assert1(LPI.getPersonalityFn() == PersonalityFn, - "Personality function doesn't match others in function", &LPI); - PersonalityFn = LPI.getPersonalityFn(); - - // All operands must be constants. - Assert1(isa<Constant>(PersonalityFn), "Personality function is not constant!", - &LPI); + Assert(LPI.getParent()->getLandingPadInst() == &LPI, + "LandingPadInst not the first non-PHI instruction in the block.", + &LPI); + for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { Constant *Clause = LPI.getClause(i); if (LPI.isCatch(i)) { - Assert1(isa<PointerType>(Clause->getType()), - "Catch operand does not have pointer type!", &LPI); + Assert(isa<PointerType>(Clause->getType()), + "Catch operand does not have pointer type!", &LPI); } else { - Assert1(LPI.isFilter(i), "Clause is neither catch nor filter!", &LPI); - Assert1(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero>(Clause), - "Filter operand is not an array of constants!", &LPI); + Assert(LPI.isFilter(i), "Clause is neither catch nor filter!", &LPI); + Assert(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero>(Clause), + "Filter operand is not an array of constants!", &LPI); } } @@ -2194,46 +2826,46 @@ void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { } const Use &U = I.getOperandUse(i); - Assert2(InstsInThisBlock.count(Op) || DT.dominates(Op, U), - "Instruction does not dominate all uses!", Op, &I); + Assert(InstsInThisBlock.count(Op) || DT.dominates(Op, U), + "Instruction does not dominate all uses!", Op, &I); } /// verifyInstruction - Verify that an instruction is well formed. /// void Verifier::visitInstruction(Instruction &I) { BasicBlock *BB = I.getParent(); - Assert1(BB, "Instruction not embedded in basic block!", &I); + Assert(BB, "Instruction not embedded in basic block!", &I); if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential for (User *U : I.users()) { - Assert1(U != (User*)&I || !DT.isReachableFromEntry(BB), - "Only PHI nodes may reference their own value!", &I); + Assert(U != (User *)&I || !DT.isReachableFromEntry(BB), + "Only PHI nodes may reference their own value!", &I); } } // Check that void typed values don't have names - Assert1(!I.getType()->isVoidTy() || !I.hasName(), - "Instruction has a name, but provides a void value!", &I); + Assert(!I.getType()->isVoidTy() || !I.hasName(), + "Instruction has a name, but provides a void value!", &I); // Check that the return value of the instruction is either void or a legal // value type. - Assert1(I.getType()->isVoidTy() || - I.getType()->isFirstClassType(), - "Instruction returns a non-scalar type!", &I); + Assert(I.getType()->isVoidTy() || I.getType()->isFirstClassType(), + "Instruction returns a non-scalar type!", &I); // Check that the instruction doesn't produce metadata. Calls are already // checked against the callee type. - Assert1(!I.getType()->isMetadataTy() || - isa<CallInst>(I) || isa<InvokeInst>(I), - "Invalid use of metadata!", &I); + Assert(!I.getType()->isMetadataTy() || isa<CallInst>(I) || isa<InvokeInst>(I), + "Invalid use of metadata!", &I); // Check that all uses of the instruction, if they are instructions // themselves, actually have parent basic blocks. If the use is not an // instruction, it is an error! for (Use &U : I.uses()) { if (Instruction *Used = dyn_cast<Instruction>(U.getUser())) - Assert2(Used->getParent() != nullptr, "Instruction referencing" - " instruction not embedded in a basic block!", &I, Used); + Assert(Used->getParent() != nullptr, + "Instruction referencing" + " instruction not embedded in a basic block!", + &I, Used); else { CheckFailed("Use of instruction is not an instruction!", U); return; @@ -2241,43 +2873,46 @@ void Verifier::visitInstruction(Instruction &I) { } for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { - Assert1(I.getOperand(i) != nullptr, "Instruction has null operand!", &I); + Assert(I.getOperand(i) != nullptr, "Instruction has null operand!", &I); // Check to make sure that only first-class-values are operands to // instructions. if (!I.getOperand(i)->getType()->isFirstClassType()) { - Assert1(0, "Instruction operands must be first-class values!", &I); + Assert(0, "Instruction operands must be first-class values!", &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 : - isa<InvokeInst>(I) ? e-3 : 0), - "Cannot take the address of an intrinsic!", &I); - Assert1(!F->isIntrinsic() || isa<CallInst>(I) || + Assert( + !F->isIntrinsic() || + i == (isa<CallInst>(I) ? e - 1 : isa<InvokeInst>(I) ? e - 3 : 0), + "Cannot take the address of an intrinsic!", &I); + Assert( + !F->isIntrinsic() || isa<CallInst>(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); + F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || + F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, + "Cannot invoke an intrinsinc other than" + " donothing or patchpoint", + &I); + Assert(F->getParent() == M, "Referencing function in another module!", + &I); } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { - Assert1(OpBB->getParent() == BB->getParent(), - "Referring to a basic block in another function!", &I); + Assert(OpBB->getParent() == BB->getParent(), + "Referring to a basic block in another function!", &I); } else if (Argument *OpArg = dyn_cast<Argument>(I.getOperand(i))) { - Assert1(OpArg->getParent() == BB->getParent(), - "Referring to an argument in another function!", &I); + Assert(OpArg->getParent() == BB->getParent(), + "Referring to an argument in another function!", &I); } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { - Assert1(GV->getParent() == M, "Referencing global in another module!", - &I); + Assert(GV->getParent() == M, "Referencing global in another module!", &I); } else if (isa<Instruction>(I.getOperand(i))) { verifyDominatesUse(I, i); } else if (isa<InlineAsm>(I.getOperand(i))) { - Assert1((i + 1 == e && isa<CallInst>(I)) || - (i + 3 == e && isa<InvokeInst>(I)), - "Cannot take the address of an inline asm!", &I); + Assert((i + 1 == e && isa<CallInst>(I)) || + (i + 3 == e && isa<InvokeInst>(I)), + "Cannot take the address of an inline asm!", &I); } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { if (CE->getType()->isPtrOrPtrVectorTy()) { // If we have a ConstantExpr pointer, we need to see if it came from an @@ -2303,31 +2938,37 @@ void Verifier::visitInstruction(Instruction &I) { } if (MDNode *MD = I.getMetadata(LLVMContext::MD_fpmath)) { - Assert1(I.getType()->isFPOrFPVectorTy(), - "fpmath requires a floating point result!", &I); - Assert1(MD->getNumOperands() == 1, "fpmath takes one operand!", &I); + Assert(I.getType()->isFPOrFPVectorTy(), + "fpmath requires a floating point result!", &I); + Assert(MD->getNumOperands() == 1, "fpmath takes one operand!", &I); if (ConstantFP *CFP0 = mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { APFloat Accuracy = CFP0->getValueAPF(); - Assert1(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(), - "fpmath accuracy not a positive number!", &I); + Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(), + "fpmath accuracy not a positive number!", &I); } else { - Assert1(false, "invalid fpmath accuracy!", &I); + Assert(false, "invalid fpmath accuracy!", &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); + Assert(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); + Assert(I.getType()->isPointerTy(), "nonnull applies only to pointer types", + &I); + Assert(isa<LoadInst>(I), + "nonnull applies only to load instructions, use attributes" + " for calls or invokes", + &I); + } + + if (MDNode *N = I.getDebugLoc().getAsMDNode()) { + Assert(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N); + visitMDNode(*N); } InstsInThisBlock.insert(&I); @@ -2391,6 +3032,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, ArgTys.push_back(Ty); switch (D.getArgumentKind()) { + case IITDescriptor::AK_Any: return false; // Success case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy(); case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy(); case IITDescriptor::AK_AnyVector: return !isa<VectorType>(Ty); @@ -2454,6 +3096,23 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, PointerType *ThisArgType = dyn_cast<PointerType>(Ty); return (!ThisArgType || ThisArgType->getElementType() != ReferenceType); } + case IITDescriptor::VecOfPtrsToElt: { + if (D.getArgumentNumber() >= ArgTys.size()) + return true; + VectorType * ReferenceType = + dyn_cast<VectorType> (ArgTys[D.getArgumentNumber()]); + VectorType *ThisArgVecTy = dyn_cast<VectorType>(Ty); + if (!ThisArgVecTy || !ReferenceType || + (ReferenceType->getVectorNumElements() != + ThisArgVecTy->getVectorNumElements())) + return true; + PointerType *ThisArgEltTy = + dyn_cast<PointerType>(ThisArgVecTy->getVectorElementType()); + if (!ThisArgEltTy) + return true; + return ThisArgEltTy->getElementType() != + ReferenceType->getVectorElementType(); + } } llvm_unreachable("unhandled"); } @@ -2470,7 +3129,7 @@ Verifier::VerifyIntrinsicIsVarArg(bool isVarArg, // If there are no descriptors left, then it can't be a vararg. if (Infos.empty()) - return isVarArg ? true : false; + return isVarArg; // There should be only one descriptor remaining at this point. if (Infos.size() != 1) @@ -2480,7 +3139,7 @@ Verifier::VerifyIntrinsicIsVarArg(bool isVarArg, IITDescriptor D = Infos.front(); Infos = Infos.slice(1); if (D.Kind == IITDescriptor::VarArg) - return isVarArg ? false : true; + return !isVarArg; return true; } @@ -2489,8 +3148,8 @@ Verifier::VerifyIntrinsicIsVarArg(bool isVarArg, /// void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { Function *IF = CI.getCalledFunction(); - Assert1(IF->isDeclaration(), "Intrinsic functions should never be defined!", - IF); + Assert(IF->isDeclaration(), "Intrinsic functions should never be defined!", + IF); // Verify that the intrinsic prototype lines up with what the .td files // describe. @@ -2502,31 +3161,33 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; SmallVector<Type *, 4> ArgTys; - Assert1(!VerifyIntrinsicType(IFTy->getReturnType(), TableRef, ArgTys), - "Intrinsic has incorrect return type!", IF); + Assert(!VerifyIntrinsicType(IFTy->getReturnType(), TableRef, ArgTys), + "Intrinsic has incorrect return type!", IF); for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i) - Assert1(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys), - "Intrinsic has incorrect argument type!", IF); + Assert(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys), + "Intrinsic has incorrect argument type!", IF); // Verify if the intrinsic call matches the vararg property. if (IsVarArg) - Assert1(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef), - "Intrinsic was not defined with variable arguments!", IF); + Assert(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef), + "Intrinsic was not defined with variable arguments!", IF); else - Assert1(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef), - "Callsite was not defined with variable arguments!", IF); + Assert(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef), + "Callsite was not defined with variable arguments!", IF); // All descriptors should be absorbed by now. - Assert1(TableRef.empty(), "Intrinsic has too few arguments!", IF); + Assert(TableRef.empty(), "Intrinsic has too few arguments!", IF); // Now that we have the intrinsic ID and the actual argument types (and we // know they are legal for the intrinsic!) get the intrinsic name through the // usual means. This allows us to verify the mangling of argument types into // the name. const std::string ExpectedName = Intrinsic::getName(ID, ArgTys); - Assert1(ExpectedName == IF->getName(), - "Intrinsic name not mangled correctly for type arguments! " - "Should be: " + ExpectedName, IF); + Assert(ExpectedName == IF->getName(), + "Intrinsic name not mangled correctly for type arguments! " + "Should be: " + + ExpectedName, + IF); // If the intrinsic takes MDNode arguments, verify that they are either global // or are local to *this* function. @@ -2539,309 +3200,432 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { break; case Intrinsic::ctlz: // llvm.ctlz case Intrinsic::cttz: // llvm.cttz - Assert1(isa<ConstantInt>(CI.getArgOperand(1)), - "is_zero_undef argument of bit counting intrinsics must be a " - "constant int", &CI); + Assert(isa<ConstantInt>(CI.getArgOperand(1)), + "is_zero_undef argument of bit counting intrinsics must be a " + "constant int", + &CI); + break; + case Intrinsic::dbg_declare: // llvm.dbg.declare + Assert(isa<MetadataAsValue>(CI.getArgOperand(0)), + "invalid llvm.dbg.declare intrinsic call 1", &CI); + visitDbgIntrinsic("declare", cast<DbgDeclareInst>(CI)); + break; + case Intrinsic::dbg_value: // llvm.dbg.value + visitDbgIntrinsic("value", cast<DbgValueInst>(CI)); break; - case Intrinsic::dbg_declare: { // llvm.dbg.declare - Assert1(CI.getArgOperand(0) && isa<MetadataAsValue>(CI.getArgOperand(0)), - "invalid llvm.dbg.declare intrinsic call 1", &CI); - } break; case Intrinsic::memcpy: case Intrinsic::memmove: - case Intrinsic::memset: - Assert1(isa<ConstantInt>(CI.getArgOperand(3)), - "alignment argument of memory intrinsics must be a constant int", - &CI); - Assert1(isa<ConstantInt>(CI.getArgOperand(4)), - "isvolatile argument of memory intrinsics must be a constant int", - &CI); + case Intrinsic::memset: { + ConstantInt *AlignCI = dyn_cast<ConstantInt>(CI.getArgOperand(3)); + Assert(AlignCI, + "alignment argument of memory intrinsics must be a constant int", + &CI); + const APInt &AlignVal = AlignCI->getValue(); + Assert(AlignCI->isZero() || AlignVal.isPowerOf2(), + "alignment argument of memory intrinsics must be a power of 2", &CI); + Assert(isa<ConstantInt>(CI.getArgOperand(4)), + "isvolatile argument of memory intrinsics must be a constant int", + &CI); break; + } case Intrinsic::gcroot: case Intrinsic::gcwrite: case Intrinsic::gcread: if (ID == Intrinsic::gcroot) { AllocaInst *AI = dyn_cast<AllocaInst>(CI.getArgOperand(0)->stripPointerCasts()); - Assert1(AI, "llvm.gcroot parameter #1 must be an alloca.", &CI); - Assert1(isa<Constant>(CI.getArgOperand(1)), - "llvm.gcroot parameter #2 must be a constant.", &CI); - if (!AI->getType()->getElementType()->isPointerTy()) { - Assert1(!isa<ConstantPointerNull>(CI.getArgOperand(1)), - "llvm.gcroot parameter #1 must either be a pointer alloca, " - "or argument #2 must be a non-null constant.", &CI); + Assert(AI, "llvm.gcroot parameter #1 must be an alloca.", &CI); + Assert(isa<Constant>(CI.getArgOperand(1)), + "llvm.gcroot parameter #2 must be a constant.", &CI); + if (!AI->getAllocatedType()->isPointerTy()) { + Assert(!isa<ConstantPointerNull>(CI.getArgOperand(1)), + "llvm.gcroot parameter #1 must either be a pointer alloca, " + "or argument #2 must be a non-null constant.", + &CI); } } - Assert1(CI.getParent()->getParent()->hasGC(), - "Enclosing function does not use GC.", &CI); + Assert(CI.getParent()->getParent()->hasGC(), + "Enclosing function does not use GC.", &CI); break; case Intrinsic::init_trampoline: - Assert1(isa<Function>(CI.getArgOperand(1)->stripPointerCasts()), - "llvm.init_trampoline parameter #2 must resolve to a function.", - &CI); + Assert(isa<Function>(CI.getArgOperand(1)->stripPointerCasts()), + "llvm.init_trampoline parameter #2 must resolve to a function.", + &CI); break; case Intrinsic::prefetch: - Assert1(isa<ConstantInt>(CI.getArgOperand(1)) && - isa<ConstantInt>(CI.getArgOperand(2)) && - cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue() < 2 && - cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue() < 4, - "invalid arguments to llvm.prefetch", - &CI); + Assert(isa<ConstantInt>(CI.getArgOperand(1)) && + isa<ConstantInt>(CI.getArgOperand(2)) && + cast<ConstantInt>(CI.getArgOperand(1))->getZExtValue() < 2 && + cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue() < 4, + "invalid arguments to llvm.prefetch", &CI); break; case Intrinsic::stackprotector: - Assert1(isa<AllocaInst>(CI.getArgOperand(1)->stripPointerCasts()), - "llvm.stackprotector parameter #2 must resolve to an alloca.", - &CI); + Assert(isa<AllocaInst>(CI.getArgOperand(1)->stripPointerCasts()), + "llvm.stackprotector parameter #2 must resolve to an alloca.", &CI); break; case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: case Intrinsic::invariant_start: - Assert1(isa<ConstantInt>(CI.getArgOperand(0)), - "size argument of memory use markers must be a constant integer", - &CI); + Assert(isa<ConstantInt>(CI.getArgOperand(0)), + "size argument of memory use markers must be a constant integer", + &CI); break; case Intrinsic::invariant_end: - Assert1(isa<ConstantInt>(CI.getArgOperand(1)), - "llvm.invariant.end parameter #2 must be a constant integer", &CI); + Assert(isa<ConstantInt>(CI.getArgOperand(1)), + "llvm.invariant.end parameter #2 must be a constant integer", &CI); break; - case Intrinsic::frameallocate: { + case Intrinsic::frameescape: { BasicBlock *BB = CI.getParent(); - Assert1(BB == &BB->getParent()->front(), - "llvm.frameallocate used outside of entry block", &CI); - Assert1(!SawFrameAllocate, - "multiple calls to llvm.frameallocate in one function", &CI); - SawFrameAllocate = true; - Assert1(isa<ConstantInt>(CI.getArgOperand(0)), - "llvm.frameallocate argument must be constant integer size", &CI); + Assert(BB == &BB->getParent()->front(), + "llvm.frameescape used outside of entry block", &CI); + Assert(!SawFrameEscape, + "multiple calls to llvm.frameescape in one function", &CI); + for (Value *Arg : CI.arg_operands()) { + if (isa<ConstantPointerNull>(Arg)) + continue; // Null values are allowed as placeholders. + auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); + Assert(AI && AI->isStaticAlloca(), + "llvm.frameescape only accepts static allocas", &CI); + } + FrameEscapeInfo[BB->getParent()].first = CI.getNumArgOperands(); + SawFrameEscape = true; break; } case Intrinsic::framerecover: { Value *FnArg = CI.getArgOperand(0)->stripPointerCasts(); Function *Fn = dyn_cast<Function>(FnArg); - Assert1(Fn && !Fn->isDeclaration(), "llvm.framerecover first " - "argument must be function defined in this module", &CI); + Assert(Fn && !Fn->isDeclaration(), + "llvm.framerecover first " + "argument must be function defined in this module", + &CI); + auto *IdxArg = dyn_cast<ConstantInt>(CI.getArgOperand(2)); + Assert(IdxArg, "idx argument of llvm.framerecover must be a constant int", + &CI); + auto &Entry = FrameEscapeInfo[Fn]; + Entry.second = unsigned( + std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); break; } - case Intrinsic::experimental_gc_statepoint: { - Assert1(!CI.doesNotAccessMemory() && - !CI.onlyReadsMemory(), - "gc.statepoint must read and write memory to preserve " - "reordering restrictions required by safepoint semantics", &CI); - Assert1(!CI.isInlineAsm(), - "gc.statepoint support for inline assembly unimplemented", &CI); - - const Value *Target = CI.getArgOperand(0); - const PointerType *PT = dyn_cast<PointerType>(Target->getType()); - Assert2(PT && PT->getElementType()->isFunctionTy(), - "gc.statepoint callee must be of function pointer type", - &CI, Target); - FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); - Assert1(!TargetFuncType->isVarArg(), - "gc.statepoint support for var arg functions not implemented", &CI); - - const Value *NumCallArgsV = CI.getArgOperand(1); - Assert1(isa<ConstantInt>(NumCallArgsV), - "gc.statepoint number of arguments to underlying call " - "must be constant integer", &CI); - const int NumCallArgs = cast<ConstantInt>(NumCallArgsV)->getZExtValue(); - Assert1(NumCallArgs >= 0, - "gc.statepoint number of arguments to underlying call " - "must be positive", &CI); - Assert1(NumCallArgs == (int)TargetFuncType->getNumParams(), - "gc.statepoint mismatch in number of call args", &CI); - - const Value *Unused = CI.getArgOperand(2); - Assert1(isa<ConstantInt>(Unused) && - cast<ConstantInt>(Unused)->isNullValue(), - "gc.statepoint parameter #3 must be zero", &CI); - - // Verify that the types of the call parameter arguments match - // the type of the wrapped callee. - for (int i = 0; i < NumCallArgs; i++) { - Type *ParamType = TargetFuncType->getParamType(i); - Type *ArgType = CI.getArgOperand(3+i)->getType(); - Assert1(ArgType == ParamType, - "gc.statepoint call argument does not match wrapped " - "function type", &CI); - } - const int EndCallArgsInx = 2+NumCallArgs; - const Value *NumDeoptArgsV = CI.getArgOperand(EndCallArgsInx+1); - Assert1(isa<ConstantInt>(NumDeoptArgsV), - "gc.statepoint number of deoptimization arguments " - "must be constant integer", &CI); - const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); - Assert1(NumDeoptArgs >= 0, - "gc.statepoint number of deoptimization arguments " - "must be positive", &CI); - - Assert1(4 + NumCallArgs + NumDeoptArgs <= (int)CI.getNumArgOperands(), - "gc.statepoint too few arguments according to length fields", &CI); - - // Check that the only uses of this gc.statepoint are gc.result or - // gc.relocate calls which are tied to this statepoint and thus part - // of the same statepoint sequence - for (User *U : CI.users()) { - const CallInst *Call = dyn_cast<const CallInst>(U); - Assert2(Call, "illegal use of statepoint token", &CI, U); - if (!Call) continue; - Assert2(isGCRelocate(Call) || isGCResult(Call), - "gc.result or gc.relocate are the only value uses" - "of a gc.statepoint", &CI, U); - if (isGCResult(Call)) { - Assert2(Call->getArgOperand(0) == &CI, - "gc.result connected to wrong gc.statepoint", - &CI, Call); - } else if (isGCRelocate(Call)) { - Assert2(Call->getArgOperand(0) == &CI, - "gc.relocate connected to wrong gc.statepoint", - &CI, Call); - } - } + case Intrinsic::experimental_gc_statepoint: + Assert(!CI.isInlineAsm(), + "gc.statepoint support for inline assembly unimplemented", &CI); + Assert(CI.getParent()->getParent()->hasGC(), + "Enclosing function does not use GC.", &CI); - // Note: It is legal for a single derived pointer to be listed multiple - // times. It's non-optimal, but it is legal. It can also happen after - // insertion if we strip a bitcast away. - // Note: It is really tempting to check that each base is relocated and - // that a derived pointer is never reused as a base pointer. This turns - // out to be problematic since optimizations run after safepoint insertion - // can recognize equality properties that the insertion logic doesn't know - // about. See example statepoint.ll in the verifier subdirectory + VerifyStatepoint(ImmutableCallSite(&CI)); break; - } case Intrinsic::experimental_gc_result_int: case Intrinsic::experimental_gc_result_float: - case Intrinsic::experimental_gc_result_ptr: { + case Intrinsic::experimental_gc_result_ptr: + case Intrinsic::experimental_gc_result: { + Assert(CI.getParent()->getParent()->hasGC(), + "Enclosing function does not use GC.", &CI); // Are we tied to a statepoint properly? CallSite StatepointCS(CI.getArgOperand(0)); const Function *StatepointFn = StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr; - Assert2(StatepointFn && StatepointFn->isDeclaration() && - StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, - "gc.result operand #1 must be from a statepoint", - &CI, CI.getArgOperand(0)); + Assert(StatepointFn && StatepointFn->isDeclaration() && + StatepointFn->getIntrinsicID() == + Intrinsic::experimental_gc_statepoint, + "gc.result operand #1 must be from a statepoint", &CI, + CI.getArgOperand(0)); // Assert that result type matches wrapped callee. - const Value *Target = StatepointCS.getArgument(0); + const Value *Target = StatepointCS.getArgument(2); const PointerType *PT = cast<PointerType>(Target->getType()); const FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); - Assert1(CI.getType() == TargetFuncType->getReturnType(), - "gc.result result type does not match wrapped callee", - &CI); + Assert(CI.getType() == TargetFuncType->getReturnType(), + "gc.result result type does not match wrapped callee", &CI); break; } case Intrinsic::experimental_gc_relocate: { - // Are we tied to a statepoint properly? - CallSite StatepointCS(CI.getArgOperand(0)); - const Function *StatepointFn = - StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr; - Assert2(StatepointFn && StatepointFn->isDeclaration() && - StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, - "gc.relocate operand #1 must be from a statepoint", - &CI, CI.getArgOperand(0)); + Assert(CI.getNumArgOperands() == 3, "wrong number of arguments", &CI); + + // Check that this relocate is correctly tied to the statepoint + + // This is case for relocate on the unwinding path of an invoke statepoint + if (ExtractValueInst *ExtractValue = + dyn_cast<ExtractValueInst>(CI.getArgOperand(0))) { + Assert(isa<LandingPadInst>(ExtractValue->getAggregateOperand()), + "gc relocate on unwind path incorrectly linked to the statepoint", + &CI); + + const BasicBlock *InvokeBB = + ExtractValue->getParent()->getUniquePredecessor(); + + // Landingpad relocates should have only one predecessor with invoke + // statepoint terminator + Assert(InvokeBB, "safepoints should have unique landingpads", + ExtractValue->getParent()); + Assert(InvokeBB->getTerminator(), "safepoint block should be well formed", + InvokeBB); + Assert(isStatepoint(InvokeBB->getTerminator()), + "gc relocate should be linked to a statepoint", InvokeBB); + } + else { + // In all other cases relocate should be tied to the statepoint directly. + // This covers relocates on a normal return path of invoke statepoint and + // relocates of a call statepoint + auto Token = CI.getArgOperand(0); + Assert(isa<Instruction>(Token) && isStatepoint(cast<Instruction>(Token)), + "gc relocate is incorrectly tied to the statepoint", &CI, Token); + } + + // Verify rest of the relocate arguments + + GCRelocateOperands Ops(&CI); + ImmutableCallSite StatepointCS(Ops.getStatepoint()); // Both the base and derived must be piped through the safepoint Value* Base = CI.getArgOperand(1); - Assert1(isa<ConstantInt>(Base), - "gc.relocate operand #2 must be integer offset", &CI); - + Assert(isa<ConstantInt>(Base), + "gc.relocate operand #2 must be integer offset", &CI); + Value* Derived = CI.getArgOperand(2); - Assert1(isa<ConstantInt>(Derived), - "gc.relocate operand #3 must be integer offset", &CI); + Assert(isa<ConstantInt>(Derived), + "gc.relocate operand #3 must be integer offset", &CI); const int BaseIndex = cast<ConstantInt>(Base)->getZExtValue(); const int DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue(); // Check the bounds - Assert1(0 <= BaseIndex && - BaseIndex < (int)StatepointCS.arg_size(), - "gc.relocate: statepoint base index out of bounds", &CI); - Assert1(0 <= DerivedIndex && - DerivedIndex < (int)StatepointCS.arg_size(), - "gc.relocate: statepoint derived index out of bounds", &CI); + Assert(0 <= BaseIndex && BaseIndex < (int)StatepointCS.arg_size(), + "gc.relocate: statepoint base index out of bounds", &CI); + Assert(0 <= DerivedIndex && DerivedIndex < (int)StatepointCS.arg_size(), + "gc.relocate: statepoint derived index out of bounds", &CI); // Check that BaseIndex and DerivedIndex fall within the 'gc parameters' // section of the statepoint's argument - const int NumCallArgs = - cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue(); + Assert(StatepointCS.arg_size() > 0, + "gc.statepoint: insufficient arguments"); + Assert(isa<ConstantInt>(StatepointCS.getArgument(3)), + "gc.statement: number of call arguments must be constant integer"); + const unsigned NumCallArgs = + cast<ConstantInt>(StatepointCS.getArgument(3))->getZExtValue(); + Assert(StatepointCS.arg_size() > NumCallArgs + 5, + "gc.statepoint: mismatch in number of call arguments"); + Assert(isa<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 5)), + "gc.statepoint: number of transition arguments must be " + "a constant integer"); + const int NumTransitionArgs = + cast<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 5)) + ->getZExtValue(); + const int DeoptArgsStart = 4 + NumCallArgs + 1 + NumTransitionArgs + 1; + Assert(isa<ConstantInt>(StatepointCS.getArgument(DeoptArgsStart)), + "gc.statepoint: number of deoptimization arguments must be " + "a constant integer"); const int NumDeoptArgs = - cast<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue(); - const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4; + cast<ConstantInt>(StatepointCS.getArgument(DeoptArgsStart))->getZExtValue(); + const int GCParamArgsStart = DeoptArgsStart + 1 + NumDeoptArgs; const int GCParamArgsEnd = StatepointCS.arg_size(); - Assert1(GCParamArgsStart <= BaseIndex && - BaseIndex < GCParamArgsEnd, - "gc.relocate: statepoint base index doesn't fall within the " - "'gc parameters' section of the statepoint call", &CI); - Assert1(GCParamArgsStart <= DerivedIndex && - DerivedIndex < GCParamArgsEnd, - "gc.relocate: statepoint derived index doesn't fall within the " - "'gc parameters' section of the statepoint call", &CI); - - - // Assert that the result type matches the type of the relocated pointer + Assert(GCParamArgsStart <= BaseIndex && BaseIndex < GCParamArgsEnd, + "gc.relocate: statepoint base index doesn't fall within the " + "'gc parameters' section of the statepoint call", + &CI); + Assert(GCParamArgsStart <= DerivedIndex && DerivedIndex < GCParamArgsEnd, + "gc.relocate: statepoint derived index doesn't fall within the " + "'gc parameters' section of the statepoint call", + &CI); + + // Relocated value must be a pointer type, but gc_relocate does not need to return the + // same pointer type as the relocated pointer. It can be casted to the correct type later + // if it's desired. However, they must have the same address space. GCRelocateOperands Operands(&CI); - Assert1(Operands.derivedPtr()->getType() == CI.getType(), - "gc.relocate: relocating a pointer shouldn't change its type", - &CI); + Assert(Operands.getDerivedPtr()->getType()->isPointerTy(), + "gc.relocate: relocated value must be a gc pointer", &CI); + + // gc_relocate return type must be a pointer type, and is verified earlier in + // VerifyIntrinsicType(). + Assert(cast<PointerType>(CI.getType())->getAddressSpace() == + cast<PointerType>(Operands.getDerivedPtr()->getType())->getAddressSpace(), + "gc.relocate: relocating a pointer shouldn't change its address space", &CI); break; } }; } -void DebugInfoVerifier::verifyDebugInfo() { - if (!VerifyDebugInfo) - return; +/// \brief Carefully grab the subprogram from a local scope. +/// +/// This carefully grabs the subprogram from a local scope, avoiding the +/// built-in assertions that would typically fire. +static DISubprogram *getSubprogram(Metadata *LocalScope) { + if (!LocalScope) + return nullptr; + + if (auto *SP = dyn_cast<DISubprogram>(LocalScope)) + return SP; + + if (auto *LB = dyn_cast<DILexicalBlockBase>(LocalScope)) + return getSubprogram(LB->getRawScope()); + + // Just return null; broken scope chains are checked elsewhere. + assert(!isa<DILocalScope>(LocalScope) && "Unknown type of local scope"); + return nullptr; +} + +template <class DbgIntrinsicTy> +void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { + auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata(); + Assert(isa<ValueAsMetadata>(MD) || + (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()), + "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); + Assert(isa<DILocalVariable>(DII.getRawVariable()), + "invalid llvm.dbg." + Kind + " intrinsic variable", &DII, + DII.getRawVariable()); + Assert(isa<DIExpression>(DII.getRawExpression()), + "invalid llvm.dbg." + Kind + " intrinsic expression", &DII, + DII.getRawExpression()); + + // Ignore broken !dbg attachments; they're checked elsewhere. + if (MDNode *N = DII.getDebugLoc().getAsMDNode()) + if (!isa<DILocation>(N)) + return; - DebugInfoFinder Finder; - Finder.processModule(*M); - processInstructions(Finder); + BasicBlock *BB = DII.getParent(); + Function *F = BB ? BB->getParent() : nullptr; + + // The scopes for variables and !dbg attachments must agree. + DILocalVariable *Var = DII.getVariable(); + DILocation *Loc = DII.getDebugLoc(); + Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment", + &DII, BB, F); + + DISubprogram *VarSP = getSubprogram(Var->getRawScope()); + DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); + if (!VarSP || !LocSP) + return; // Broken scope chains are checked elsewhere. + + Assert(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind + + " variable and !dbg attachment", + &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc, + Loc->getScope()->getSubprogram()); +} + +template <class MapTy> +static uint64_t getVariableSize(const DILocalVariable &V, const MapTy &Map) { + // Be careful of broken types (checked elsewhere). + const Metadata *RawType = V.getRawType(); + while (RawType) { + // Try to get the size directly. + if (auto *T = dyn_cast<DIType>(RawType)) + if (uint64_t Size = T->getSizeInBits()) + return Size; + + if (auto *DT = dyn_cast<DIDerivedType>(RawType)) { + // Look at the base type. + RawType = DT->getRawBaseType(); + continue; + } - // Verify Debug Info. - // - // NOTE: The loud braces are necessary for MSVC compatibility. - for (DICompileUnit CU : Finder.compile_units()) { - Assert1(CU.Verify(), "DICompileUnit does not Verify!", CU); - } - for (DISubprogram S : Finder.subprograms()) { - Assert1(S.Verify(), "DISubprogram does not Verify!", S); - } - for (DIGlobalVariable GV : Finder.global_variables()) { - Assert1(GV.Verify(), "DIGlobalVariable does not Verify!", GV); - } - for (DIType T : Finder.types()) { - Assert1(T.Verify(), "DIType does not Verify!", T); + if (auto *S = dyn_cast<MDString>(RawType)) { + // Don't error on missing types (checked elsewhere). + RawType = Map.lookup(S); + continue; + } + + // Missing type or size. + break; } - for (DIScope S : Finder.scopes()) { - Assert1(S.Verify(), "DIScope does not Verify!", S); + + // Fail gracefully. + return 0; +} + +template <class MapTy> +void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I, + const MapTy &TypeRefs) { + DILocalVariable *V; + DIExpression *E; + if (auto *DVI = dyn_cast<DbgValueInst>(&I)) { + V = dyn_cast_or_null<DILocalVariable>(DVI->getRawVariable()); + E = dyn_cast_or_null<DIExpression>(DVI->getRawExpression()); + } else { + auto *DDI = cast<DbgDeclareInst>(&I); + V = dyn_cast_or_null<DILocalVariable>(DDI->getRawVariable()); + E = dyn_cast_or_null<DIExpression>(DDI->getRawExpression()); } + + // We don't know whether this intrinsic verified correctly. + if (!V || !E || !E->isValid()) + return; + + // Nothing to do if this isn't a bit piece expression. + if (!E->isBitPiece()) + return; + + // The frontend helps out GDB by emitting the members of local anonymous + // unions as artificial local variables with shared storage. When SROA splits + // the storage for artificial local variables that are smaller than the entire + // union, the overhang piece will be outside of the allotted space for the + // variable and this check fails. + // FIXME: Remove this check as soon as clang stops doing this; it hides bugs. + if (V->isArtificial()) + return; + + // If there's no size, the type is broken, but that should be checked + // elsewhere. + uint64_t VarSize = getVariableSize(*V, TypeRefs); + if (!VarSize) + return; + + unsigned PieceSize = E->getBitPieceSize(); + unsigned PieceOffset = E->getBitPieceOffset(); + Assert(PieceSize + PieceOffset <= VarSize, + "piece is larger than or outside of variable", &I, V, E); + Assert(PieceSize != VarSize, "piece covers entire variable", &I, V, E); } -void DebugInfoVerifier::processInstructions(DebugInfoFinder &Finder) { - for (const Function &F : *M) - for (auto I = inst_begin(&F), E = inst_end(&F); I != E; ++I) { - if (MDNode *MD = I->getMetadata(LLVMContext::MD_dbg)) - Finder.processLocation(*M, DILocation(MD)); - if (const CallInst *CI = dyn_cast<CallInst>(&*I)) - processCallInst(Finder, *CI); - } +void Verifier::visitUnresolvedTypeRef(const MDString *S, const MDNode *N) { + // This is in its own function so we get an error for each bad type ref (not + // just the first). + Assert(false, "unresolved type ref", S, N); } -void DebugInfoVerifier::processCallInst(DebugInfoFinder &Finder, - const CallInst &CI) { - if (Function *F = CI.getCalledFunction()) - if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) - switch (ID) { - case Intrinsic::dbg_declare: - Finder.processDeclare(*M, cast<DbgDeclareInst>(&CI)); - break; - case Intrinsic::dbg_value: - Finder.processValue(*M, cast<DbgValueInst>(&CI)); - break; - default: - break; - } +void Verifier::verifyTypeRefs() { + auto *CUs = M->getNamedMetadata("llvm.dbg.cu"); + if (!CUs) + return; + + // Visit all the compile units again to map the type references. + SmallDenseMap<const MDString *, const DIType *, 32> TypeRefs; + for (auto *CU : CUs->operands()) + if (auto Ts = cast<DICompileUnit>(CU)->getRetainedTypes()) + for (DIType *Op : Ts) + if (auto *T = dyn_cast<DICompositeType>(Op)) + if (auto *S = T->getRawIdentifier()) { + UnresolvedTypeRefs.erase(S); + TypeRefs.insert(std::make_pair(S, T)); + } + + // Verify debug info intrinsic bit piece expressions. This needs a second + // pass through the intructions, since we haven't built TypeRefs yet when + // verifying functions, and simply queuing the DbgInfoIntrinsics to evaluate + // later/now would queue up some that could be later deleted. + for (const Function &F : *M) + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) + verifyBitPieceExpression(*DII, TypeRefs); + + // Return early if all typerefs were resolved. + if (UnresolvedTypeRefs.empty()) + return; + + // Sort the unresolved references by name so the output is deterministic. + typedef std::pair<const MDString *, const MDNode *> TypeRef; + SmallVector<TypeRef, 32> Unresolved(UnresolvedTypeRefs.begin(), + UnresolvedTypeRefs.end()); + std::sort(Unresolved.begin(), Unresolved.end(), + [](const TypeRef &LHS, const TypeRef &RHS) { + return LHS.first->getString() < RHS.first->getString(); + }); + + // Visit the unresolved refs (printing out the errors). + for (const TypeRef &TR : Unresolved) + visitUnresolvedTypeRef(TR.first, TR.second); } //===----------------------------------------------------------------------===// @@ -2871,8 +3655,7 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS) { // Note that this function's return value is inverted from what you would // expect of a function called "verify". - DebugInfoVerifier DIV(OS ? *OS : NullStr); - return !V.verify(M) || !DIV.verify(M) || Broken; + return !V.verify(M) || Broken; } namespace { @@ -2882,7 +3665,7 @@ struct VerifierLegacyPass : public FunctionPass { Verifier V; bool FatalErrors; - VerifierLegacyPass() : FunctionPass(ID), FatalErrors(true) { + VerifierLegacyPass() : FunctionPass(ID), V(dbgs()), FatalErrors(true) { initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); } explicit VerifierLegacyPass(bool FatalErrors) @@ -2908,48 +3691,15 @@ struct VerifierLegacyPass : public FunctionPass { AU.setPreservesAll(); } }; -struct DebugInfoVerifierLegacyPass : public ModulePass { - static char ID; - - DebugInfoVerifier V; - bool FatalErrors; - - DebugInfoVerifierLegacyPass() : ModulePass(ID), FatalErrors(true) { - initializeDebugInfoVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); - } - explicit DebugInfoVerifierLegacyPass(bool FatalErrors) - : ModulePass(ID), V(dbgs()), FatalErrors(FatalErrors) { - initializeDebugInfoVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); - } - - bool runOnModule(Module &M) override { - if (!V.verify(M) && FatalErrors) - report_fatal_error("Broken debug info found, compilation aborted!"); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } -}; -} +} // namespace char VerifierLegacyPass::ID = 0; INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false) -char DebugInfoVerifierLegacyPass::ID = 0; -INITIALIZE_PASS(DebugInfoVerifierLegacyPass, "verify-di", "Debug Info Verifier", - false, false) - FunctionPass *llvm::createVerifierPass(bool FatalErrors) { return new VerifierLegacyPass(FatalErrors); } -ModulePass *llvm::createDebugInfoVerifierPass(bool FatalErrors) { - return new DebugInfoVerifierLegacyPass(FatalErrors); -} - PreservedAnalyses VerifierPass::run(Module &M) { if (verifyModule(M, &dbgs()) && FatalErrors) report_fatal_error("Broken module found, compilation aborted!"); |