X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FIR%2FAsmWriter.cpp;h=5ab6953bdbd1b5391a1480710f2a8c1d80405aa8;hp=7fcab5c921b7b8e349c38636bb9aad01af56e1f3;hb=5a70dd1d8286faa4713b60da7621094d892e2ffc;hpb=2925be515b30aa8a69d156849aaf5896c5cbcc9a diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 7fcab5c921b..5ab6953bdbd 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -49,6 +49,218 @@ AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} // Helper Functions //===----------------------------------------------------------------------===// +namespace { +struct OrderMap { + DenseMap> IDs; + + unsigned size() const { return IDs.size(); } + std::pair &operator[](const Value *V) { return IDs[V]; } + std::pair lookup(const Value *V) const { + return IDs.lookup(V); + } + void index(const Value *V) { + // Explicitly sequence get-size and insert-value operations to avoid UB. + unsigned ID = IDs.size() + 1; + IDs[V].first = ID; + } +}; +} + +static void orderValue(const Value *V, OrderMap &OM) { + if (OM.lookup(V).first) + return; + + if (const Constant *C = dyn_cast(V)) + if (C->getNumOperands() && !isa(C)) + for (const Value *Op : C->operands()) + if (!isa(Op) && !isa(Op)) + orderValue(Op, OM); + + // Note: we cannot cache this lookup above, since inserting into the map + // changes the map's size, and thus affects the other IDs. + OM.index(V); +} + +static OrderMap orderModule(const Module *M) { + // This needs to match the order used by ValueEnumerator::ValueEnumerator() + // and ValueEnumerator::incorporateFunction(). + OrderMap OM; + + for (const GlobalVariable &G : M->globals()) { + if (G.hasInitializer()) + if (!isa(G.getInitializer())) + orderValue(G.getInitializer(), OM); + orderValue(&G, OM); + } + for (const GlobalAlias &A : M->aliases()) { + if (!isa(A.getAliasee())) + orderValue(A.getAliasee(), OM); + orderValue(&A, OM); + } + for (const Function &F : *M) { + if (F.hasPrefixData()) + if (!isa(F.getPrefixData())) + orderValue(F.getPrefixData(), OM); + + if (F.hasPrologueData()) + if (!isa(F.getPrologueData())) + orderValue(F.getPrologueData(), OM); + + orderValue(&F, OM); + + if (F.isDeclaration()) + continue; + + for (const Argument &A : F.args()) + orderValue(&A, OM); + for (const BasicBlock &BB : F) { + orderValue(&BB, OM); + for (const Instruction &I : BB) { + for (const Value *Op : I.operands()) + if ((isa(*Op) && !isa(*Op)) || + isa(*Op)) + orderValue(Op, OM); + orderValue(&I, OM); + } + } + } + return OM; +} + +static void predictValueUseListOrderImpl(const Value *V, const Function *F, + unsigned ID, const OrderMap &OM, + UseListOrderStack &Stack) { + // Predict use-list order for this one. + typedef std::pair Entry; + SmallVector List; + for (const Use &U : V->uses()) + // Check if this user will be serialized. + if (OM.lookup(U.getUser()).first) + List.push_back(std::make_pair(&U, List.size())); + + if (List.size() < 2) + // We may have lost some users. + return; + + bool GetsReversed = + !isa(V) && !isa(V) && !isa(V); + if (auto *BA = dyn_cast(V)) + ID = OM.lookup(BA->getBasicBlock()).first; + std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) { + const Use *LU = L.first; + const Use *RU = R.first; + if (LU == RU) + return false; + + auto LID = OM.lookup(LU->getUser()).first; + auto RID = OM.lookup(RU->getUser()).first; + + // If ID is 4, then expect: 7 6 5 1 2 3. + if (LID < RID) { + if (GetsReversed) + if (RID <= ID) + return true; + return false; + } + if (RID < LID) { + if (GetsReversed) + if (LID <= ID) + return false; + return true; + } + + // LID and RID are equal, so we have different operands of the same user. + // Assume operands are added in order for all instructions. + if (GetsReversed) + if (LID <= ID) + return LU->getOperandNo() < RU->getOperandNo(); + return LU->getOperandNo() > RU->getOperandNo(); + }); + + if (std::is_sorted( + List.begin(), List.end(), + [](const Entry &L, const Entry &R) { return L.second < R.second; })) + // Order is already correct. + return; + + // Store the shuffle. + Stack.emplace_back(V, F, List.size()); + assert(List.size() == Stack.back().Shuffle.size() && "Wrong size"); + for (size_t I = 0, E = List.size(); I != E; ++I) + Stack.back().Shuffle[I] = List[I].second; +} + +static void predictValueUseListOrder(const Value *V, const Function *F, + OrderMap &OM, UseListOrderStack &Stack) { + auto &IDPair = OM[V]; + assert(IDPair.first && "Unmapped value"); + if (IDPair.second) + // Already predicted. + return; + + // Do the actual prediction. + IDPair.second = true; + if (!V->use_empty() && std::next(V->use_begin()) != V->use_end()) + predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack); + + // Recursive descent into constants. + if (const Constant *C = dyn_cast(V)) + if (C->getNumOperands()) // Visit GlobalValues. + for (const Value *Op : C->operands()) + if (isa(Op)) // Visit GlobalValues. + predictValueUseListOrder(Op, F, OM, Stack); +} + +static UseListOrderStack predictUseListOrder(const Module *M) { + OrderMap OM = orderModule(M); + + // Use-list orders need to be serialized after all the users have been added + // to a value, or else the shuffles will be incomplete. Store them per + // function in a stack. + // + // Aside from function order, the order of values doesn't matter much here. + UseListOrderStack Stack; + + // We want to visit the functions backward now so we can list function-local + // constants in the last Function they're used in. Module-level constants + // have already been visited above. + for (auto I = M->rbegin(), E = M->rend(); I != E; ++I) { + const Function &F = *I; + if (F.isDeclaration()) + continue; + for (const BasicBlock &BB : F) + predictValueUseListOrder(&BB, &F, OM, Stack); + for (const Argument &A : F.args()) + predictValueUseListOrder(&A, &F, OM, Stack); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + for (const Value *Op : I.operands()) + if (isa(*Op) || isa(*Op)) // Visit GlobalValues. + predictValueUseListOrder(Op, &F, OM, Stack); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + predictValueUseListOrder(&I, &F, OM, Stack); + } + + // Visit globals last. + for (const GlobalVariable &G : M->globals()) + predictValueUseListOrder(&G, nullptr, OM, Stack); + for (const Function &F : *M) + predictValueUseListOrder(&F, nullptr, OM, Stack); + for (const GlobalAlias &A : M->aliases()) + predictValueUseListOrder(&A, nullptr, OM, Stack); + for (const GlobalVariable &G : M->globals()) + if (G.hasInitializer()) + predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack); + for (const GlobalAlias &A : M->aliases()) + predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack); + for (const Function &F : *M) + if (F.hasPrefixData()) + predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack); + + return Stack; +} + static const Module *getModuleFromVal(const Value *V) { if (const Argument *MA = dyn_cast(V)) return MA->getParent() ? MA->getParent()->getParent() : nullptr; @@ -75,9 +287,11 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::AnyReg: Out << "anyregcc"; break; case CallingConv::PreserveMost: Out << "preserve_mostcc"; break; case CallingConv::PreserveAll: Out << "preserve_allcc"; break; + case CallingConv::GHC: Out << "ghccc"; break; case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break; case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break; case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break; + case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break; case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break; case CallingConv::ARM_APCS: Out << "arm_apcscc"; break; case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break; @@ -347,6 +561,8 @@ public: FunctionProcessed = false; } + const Function *getFunction() const { return TheFunction; } + /// After calling incorporateFunction, use this method to remove the /// most recently incorporated function from the SlotTracker. This /// will reset the state of the machine back to just the module contents. @@ -390,8 +606,8 @@ 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; + SlotTracker(const SlotTracker &) = delete; + void operator=(const SlotTracker &) = delete; }; SlotTracker *createSlotTracker(const Module *M) { @@ -418,13 +634,6 @@ static SlotTracker *createSlotTracker(const Value *V) { if (const Function *Func = dyn_cast(V)) return new SlotTracker(Func); - if (const MDNode *MD = dyn_cast(V)) { - if (!MD->isFunctionLocal()) - return new SlotTracker(MD->getFunction()); - - return new SlotTracker((Function *)nullptr); - } - return nullptr; } @@ -437,16 +646,14 @@ 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), fNext(0), mdnNext(0), asNext(0) { -} + : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), 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) - : TheModule(F ? F->getParent() : nullptr), TheFunction(F), - FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) { -} + : TheModule(F ? F->getParent() : nullptr), TheFunction(F), + FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {} inline void SlotTracker::initialize() { if (TheModule) { @@ -508,7 +715,7 @@ void SlotTracker::processFunction() { ST_DEBUG("Inserting Instructions:\n"); - SmallVector, 4> MDForInst; + SmallVector, 4> MDForInst; // Add all of the basic blocks and instructions with no names. for (Function::const_iterator BB = TheFunction->begin(), @@ -528,8 +735,9 @@ void SlotTracker::processFunction() { if (Function *F = CI->getCalledFunction()) if (F->isIntrinsic()) for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) - if (MDNode *N = dyn_cast_or_null(I->getOperand(i))) - CreateMetadataSlot(N); + if (auto *V = dyn_cast_or_null(I->getOperand(i))) + if (MDNode *N = dyn_cast(V->getMetadata())) + CreateMetadataSlot(N); // Add all the call attributes to the table. AttributeSet Attrs = CI->getAttributes().getFnAttributes(); @@ -640,16 +848,10 @@ void SlotTracker::CreateFunctionSlot(const Value *V) { void SlotTracker::CreateMetadataSlot(const MDNode *N) { assert(N && "Can't insert a null Value into SlotTracker!"); - // Don't insert if N is a function-local metadata, these are always printed - // inline. - if (!N->isFunctionLocal()) { - mdn_iterator I = mdnMap.find(N); - if (I != mdnMap.end()) - return; - - unsigned DestSlot = mdnNext++; - mdnMap[N] = DestSlot; - } + unsigned DestSlot = mdnNext; + if (!mdnMap.insert(std::make_pair(N, DestSlot)).second) + return; + ++mdnNext; // Recursively add any MDNodes referenced by operands. for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) @@ -678,6 +880,11 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, SlotTracker *Machine, const Module *Context); +static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context, + bool FromValue = false); + static const char *getPredicateText(unsigned predicate) { const char * pred = "unknown"; switch (predicate) { @@ -803,7 +1010,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; } } @@ -1016,6 +1223,14 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << ' ' << getPredicateText(CE->getPredicate()); Out << " ("; + if (const GEPOperator *GEP = dyn_cast(CE)) { + TypePrinter.print( + cast(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 << ' '; @@ -1042,20 +1257,21 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << ""; } -static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { +static void writeMDTuple(raw_ostream &Out, const MDTuple *Node, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { Out << "!{"; for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) { - const Value *V = Node->getOperand(mi); - if (!V) + const Metadata *MD = Node->getOperand(mi); + if (!MD) Out << "null"; - else { + else if (auto *MDV = dyn_cast(MD)) { + Value *V = MDV->getValue(); TypePrinter->print(V->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, Node->getOperand(mi), - TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context); + } else { + WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context); } if (mi + 1 != me) Out << ", "; @@ -1064,6 +1280,619 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, Out << "}"; } +namespace { +struct FieldSeparator { + bool Skip; + 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 << FS.Sep; +} +} // end namespace + +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); +} + +static void writeTag(raw_ostream &Out, FieldSeparator &FS, const DebugNode *N) { + Out << FS << "tag: "; + if (const char *Tag = dwarf::TagString(N->getTag())) + Out << Tag; + else + Out << N->getTag(); +} + +static void writeStringField(raw_ostream &Out, FieldSeparator &FS, + StringRef Name, StringRef Value, + bool ShouldSkipEmpty = true) { + if (ShouldSkipEmpty && Value.empty()) + return; + + Out << FS << Name << ": \""; + PrintEscapedString(Value, Out); + Out << "\""; +} + +static void writeGenericDebugNode(raw_ostream &Out, const GenericDebugNode *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!GenericDebugNode("; + FieldSeparator FS; + writeTag(Out, FS, N); + writeStringField(Out, FS, "header", N->getHeader()); + if (N->getNumDwarfOperands()) { + Out << FS << "operands: {"; + FieldSeparator IFS; + for (auto &I : N->dwarf_operands()) { + Out << IFS; + writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context); + } + Out << "}"; + } + Out << ")"; +} + +static void writeMDLocation(raw_ostream &Out, const MDLocation *DL, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDLocation("; + FieldSeparator FS; + // 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); + } + Out << ")"; +} + +static void writeMDSubrange(raw_ostream &Out, const MDSubrange *N, + TypePrinting *, SlotTracker *, const Module *) { + Out << "!MDSubrange("; + FieldSeparator FS; + Out << FS << "count: " << N->getCount(); + if (N->getLo()) + Out << FS << "lowerBound: " << N->getLo(); + Out << ")"; +} + +static void writeMDEnumerator(raw_ostream &Out, const MDEnumerator *N, + TypePrinting *, SlotTracker *, const Module *) { + Out << "!MDEnumerator("; + FieldSeparator FS; + writeStringField(Out, FS, "name", N->getName(), /* ShouldSkipEmpty */ false); + Out << FS << "value: " << N->getValue(); + Out << ")"; +} + +static void writeMDBasicType(raw_ostream &Out, const MDBasicType *N, + TypePrinting *, SlotTracker *, const Module *) { + Out << "!MDBasicType("; + FieldSeparator FS; + if (N->getTag() != dwarf::DW_TAG_base_type) + writeTag(Out, FS, N); + writeStringField(Out, FS, "name", N->getName()); + if (N->getSizeInBits()) + Out << FS << "size: " << N->getSizeInBits(); + if (N->getAlignInBits()) + Out << FS << "align: " << N->getAlignInBits(); + if (unsigned Encoding = N->getEncoding()) { + Out << FS << "encoding: "; + if (const char *S = dwarf::AttributeEncodingString(Encoding)) + Out << S; + else + Out << Encoding; + } + Out << ")"; +} + +static void writeDIFlags(raw_ostream &Out, unsigned Flags) { + SmallVector SplitFlags; + unsigned Extra = DIDescriptor::splitFlags(Flags, SplitFlags); + + FieldSeparator FS(" | "); + for (unsigned F : SplitFlags) { + const char *StringF = DIDescriptor::getFlagString(F); + assert(StringF && "Expected valid flag"); + Out << FS << StringF; + } + if (Extra || SplitFlags.empty()) + Out << FS << Extra; +} + +static void writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDDerivedType("; + FieldSeparator FS; + writeTag(Out, FS, N); + writeStringField(Out, FS, "name", N->getName()); + if (N->getScope()) { + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + } + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + Out << FS << "baseType: "; + writeMetadataAsOperand(Out, N->getBaseType(), TypePrinter, Machine, Context); + if (N->getSizeInBits()) + Out << FS << "size: " << N->getSizeInBits(); + if (N->getAlignInBits()) + Out << FS << "align: " << N->getAlignInBits(); + if (N->getOffsetInBits()) + Out << FS << "offset: " << N->getOffsetInBits(); + if (auto Flags = N->getFlags()) { + Out << FS << "flags: "; + writeDIFlags(Out, Flags); + } + if (N->getExtraData()) { + Out << FS << "extraData: "; + writeMetadataAsOperand(Out, N->getExtraData(), TypePrinter, Machine, + Context); + } + Out << ")"; +} + +static void writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!MDCompositeType("; + FieldSeparator FS; + writeTag(Out, FS, N); + writeStringField(Out, FS, "name", N->getName()); + if (N->getScope()) { + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + } + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getBaseType()) { + Out << FS << "baseType: "; + writeMetadataAsOperand(Out, N->getBaseType(), TypePrinter, Machine, + Context); + } + if (N->getSizeInBits()) + Out << FS << "size: " << N->getSizeInBits(); + if (N->getAlignInBits()) + Out << FS << "align: " << N->getAlignInBits(); + if (N->getOffsetInBits()) + Out << FS << "offset: " << N->getOffsetInBits(); + if (auto Flags = N->getFlags()) { + Out << FS << "flags: "; + writeDIFlags(Out, Flags); + } + if (N->getElements()) { + Out << FS << "elements: "; + writeMetadataAsOperand(Out, N->getElements(), TypePrinter, Machine, + Context); + } + if (unsigned Lang = N->getRuntimeLang()) { + Out << FS << "runtimeLang: "; + if (const char *S = dwarf::LanguageString(Lang)) + Out << S; + else + Out << Lang; + } + + if (N->getVTableHolder()) { + Out << FS << "vtableHolder: "; + writeMetadataAsOperand(Out, N->getVTableHolder(), TypePrinter, Machine, + Context); + } + if (N->getTemplateParams()) { + Out << FS << "templateParams: "; + writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine, + Context); + } + writeStringField(Out, FS, "identifier", N->getIdentifier()); + Out << ")"; +} + +static void writeMDSubroutineType(raw_ostream &Out, const MDSubroutineType *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!MDSubroutineType("; + FieldSeparator FS; + if (auto Flags = N->getFlags()) { + Out << FS << "flags: "; + writeDIFlags(Out, Flags); + } + Out << FS << "types: "; + writeMetadataAsOperand(Out, N->getTypeArray(), TypePrinter, Machine, Context); + Out << ")"; +} + +static void writeMDFile(raw_ostream &Out, const MDFile *N, TypePrinting *, + SlotTracker *, const Module *) { + Out << "!MDFile("; + FieldSeparator FS; + writeStringField(Out, FS, "filename", N->getFilename(), + /* ShouldSkipEmpty */ false); + writeStringField(Out, FS, "directory", N->getDirectory(), + /* ShouldSkipEmpty */ false); + Out << ")"; +} + +static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDCompileUnit("; + FieldSeparator FS; + Out << FS << "language: "; + if (const char *Lang = dwarf::LanguageString(N->getSourceLanguage())) + Out << Lang; + else + Out << N->getSourceLanguage(); + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, Context); + writeStringField(Out, FS, "producer", N->getProducer()); + Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false"); + writeStringField(Out, FS, "flags", N->getFlags()); + Out << FS << "runtimeVersion: " << N->getRuntimeVersion(); + writeStringField(Out, FS, "splitDebugFilename", N->getSplitDebugFilename()); + Out << FS << "emissionKind: " << N->getEmissionKind(); + if (N->getEnumTypes()) { + Out << FS << "enums: "; + writeMetadataAsOperand(Out, N->getEnumTypes(), TypePrinter, Machine, + Context); + } + if (N->getRetainedTypes()) { + Out << FS << "retainedTypes: "; + writeMetadataAsOperand(Out, N->getRetainedTypes(), TypePrinter, Machine, + Context); + } + if (N->getSubprograms()) { + Out << FS << "subprograms: "; + writeMetadataAsOperand(Out, N->getSubprograms(), TypePrinter, Machine, + Context); + } + if (N->getGlobalVariables()) { + Out << FS << "globals: "; + writeMetadataAsOperand(Out, N->getGlobalVariables(), TypePrinter, Machine, + Context); + } + if (N->getImportedEntities()) { + Out << FS << "imports: "; + writeMetadataAsOperand(Out, N->getImportedEntities(), TypePrinter, Machine, + Context); + } + Out << ")"; +} + +static void writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDSubprogram("; + FieldSeparator FS; + writeStringField(Out, FS, "name", N->getName()); + writeStringField(Out, FS, "linkageName", N->getLinkageName()); + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getType()) { + Out << FS << "type: "; + writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, + Context); + } + Out << FS << "isLocal: " << (N->isLocalToUnit() ? "true" : "false"); + Out << FS << "isDefinition: " << (N->isDefinition() ? "true" : "false"); + if (N->getScopeLine()) + Out << FS << "scopeLine: " << N->getScopeLine(); + if (N->getContainingType()) { + Out << FS << "containingType: "; + writeMetadataAsOperand(Out, N->getContainingType(), TypePrinter, Machine, + Context); + } + if (unsigned V = N->getVirtuality()) { + Out << FS << "virtuality: "; + if (const char *S = dwarf::VirtualityString(V)) + Out << S; + else + Out << V; + } + if (N->getVirtualIndex()) + Out << FS << "virtualIndex: " << N->getVirtualIndex(); + if (auto Flags = N->getFlags()) { + Out << FS << "flags: "; + writeDIFlags(Out, Flags); + } + Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false"); + if (N->getFunction()) { + Out << FS << "function: "; + writeMetadataAsOperand(Out, N->getFunction(), TypePrinter, Machine, + Context); + } + if (N->getTemplateParams()) { + Out << FS << "templateParams: "; + writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine, + Context); + } + if (N->getDeclaration()) { + Out << FS << "declaration: "; + writeMetadataAsOperand(Out, N->getDeclaration(), TypePrinter, Machine, + Context); + } + if (N->getVariables()) { + Out << FS << "variables: "; + writeMetadataAsOperand(Out, N->getVariables(), TypePrinter, Machine, + Context); + } + Out << ")"; +} + +static void writeMDLexicalBlock(raw_ostream &Out, const MDLexicalBlock *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDLexicalBlock("; + FieldSeparator FS; + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getColumn()) + Out << FS << "column: " << N->getColumn(); + Out << ")"; +} + +static void writeMDLexicalBlockFile(raw_ostream &Out, + const MDLexicalBlockFile *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!MDLexicalBlockFile("; + FieldSeparator FS; + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + Out << FS << "discriminator: " << N->getDiscriminator(); + Out << ")"; +} + +static void writeMDNamespace(raw_ostream &Out, const MDNamespace *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDNamespace("; + FieldSeparator FS; + writeStringField(Out, FS, "name", N->getName()); + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + Out << ")"; +} + +static void writeMDTemplateTypeParameter(raw_ostream &Out, + const MDTemplateTypeParameter *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!MDTemplateTypeParameter("; + FieldSeparator FS; + writeStringField(Out, FS, "name", N->getName()); + Out << FS << "type: "; + writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context); + Out << ")"; +} + +static void writeMDTemplateValueParameter(raw_ostream &Out, + const MDTemplateValueParameter *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!MDTemplateValueParameter("; + FieldSeparator FS; + if (N->getTag() != dwarf::DW_TAG_template_value_parameter) + writeTag(Out, FS, N); + writeStringField(Out, FS, "name", N->getName()); + if (auto *Type = N->getType()) { + Out << FS << "type: "; + writeMetadataAsOperand(Out, Type, TypePrinter, Machine, Context); + } + Out << FS << "value: "; + writeMetadataAsOperand(Out, N->getValue(), TypePrinter, Machine, Context); + Out << ")"; +} + +static void writeMDGlobalVariable(raw_ostream &Out, const MDGlobalVariable *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!MDGlobalVariable("; + FieldSeparator FS; + writeStringField(Out, FS, "name", N->getName()); + writeStringField(Out, FS, "linkageName", N->getLinkageName()); + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getType()) { + Out << FS << "type: "; + writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, + Context); + } + Out << FS << "isLocal: " << (N->isLocalToUnit() ? "true" : "false"); + Out << FS << "isDefinition: " << (N->isDefinition() ? "true" : "false"); + if (N->getVariable()) { + Out << FS << "variable: "; + writeMetadataAsOperand(Out, N->getVariable(), TypePrinter, Machine, + Context); + } + if (N->getStaticDataMemberDeclaration()) { + Out << FS << "declaration: "; + writeMetadataAsOperand(Out, N->getStaticDataMemberDeclaration(), + TypePrinter, Machine, Context); + } + Out << ")"; +} + +static void writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!MDLocalVariable("; + FieldSeparator FS; + writeTag(Out, FS, N); + writeStringField(Out, FS, "name", N->getName()); + if (N->getTag() == dwarf::DW_TAG_arg_variable || N->getArg()) + Out << FS << "arg: " << N->getArg(); + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getType()) { + Out << FS << "type: "; + writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, + Context); + } + if (auto Flags = N->getFlags()) { + Out << FS << "flags: "; + writeDIFlags(Out, Flags); + } + if (N->getInlinedAt()) { + Out << FS << "inlinedAt: "; + writeMetadataAsOperand(Out, N->getInlinedAt(), TypePrinter, Machine, + Context); + } + Out << ")"; +} + +static void writeMDExpression(raw_ostream &Out, const MDExpression *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDExpression("; + 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 writeMDObjCProperty(raw_ostream &Out, const MDObjCProperty *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDObjCProperty("; + FieldSeparator FS; + writeStringField(Out, FS, "name", N->getName()); + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + writeStringField(Out, FS, "setter", N->getSetterName()); + writeStringField(Out, FS, "getter", N->getGetterName()); + if (N->getAttributes()) + Out << FS << "attributes: " << N->getAttributes(); + if (N->getType()) { + Out << FS << "type: "; + writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context); + } + Out << ")"; +} + +static void writeMDImportedEntity(raw_ostream &Out, const MDImportedEntity *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!MDImportedEntity("; + FieldSeparator FS; + writeTag(Out, FS, N); + writeStringField(Out, FS, "name", N->getName()); + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + if (N->getEntity()) { + Out << FS << "entity: "; + writeMetadataAsOperand(Out, N->getEntity(), TypePrinter, Machine, Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + Out << ")"; +} + + +static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + assert(!Node->isTemporary() && "Unexpected forward declaration"); + + if (Node->isDistinct()) + Out << "distinct "; + + switch (Node->getMetadataID()) { + default: + llvm_unreachable("Expected uniquable MDNode"); +#define HANDLE_MDNODE_LEAF(CLASS) \ + case Metadata::CLASS##Kind: \ + write##CLASS(Out, cast(Node), TypePrinter, Machine, Context); \ + break; +#include "llvm/IR/Metadata.def" + } +} + // Full implementation of printing a Value as an operand with support for // TypePrinting, etc. static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, @@ -1099,31 +1928,9 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, return; } - if (const MDNode *N = dyn_cast(V)) { - if (N->isFunctionLocal()) { - // Print metadata inline, not via slot reference number. - WriteMDNodeBodyInternal(Out, N, TypePrinter, Machine, Context); - return; - } - - if (!Machine) { - if (N->isFunctionLocal()) - Machine = new SlotTracker(N->getFunction()); - else - Machine = new SlotTracker(Context); - } - int Slot = Machine->getMetadataSlot(N); - if (Slot == -1) - Out << ""; - else - Out << '!' << Slot; - return; - } - - if (const MDString *MDS = dyn_cast(V)) { - Out << "!\""; - PrintEscapedString(MDS->getString(), Out); - Out << '"'; + if (auto *MD = dyn_cast(V)) { + WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine, + Context, /* FromValue */ true); return; } @@ -1166,6 +1973,40 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, Out << ""; } +static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context, + bool FromValue) { + if (const MDNode *N = dyn_cast(MD)) { + if (!Machine) + Machine = new SlotTracker(Context); + int Slot = Machine->getMetadataSlot(N); + if (Slot == -1) + // Give the pointer value instead of "badref", since this comes up all + // the time when debugging. + Out << "<" << N << ">"; + else + Out << '!' << Slot; + return; + } + + if (const MDString *MDS = dyn_cast(MD)) { + Out << "!\""; + PrintEscapedString(MDS->getString(), Out); + Out << '"'; + return; + } + + auto *V = cast(MD); + assert(TypePrinter && "TypePrinter required for metadata values"); + assert((FromValue || !isa(V)) && + "Unexpected function-local metadata outside of value argument"); + + TypePrinter->print(V->getValue()->getType(), Out); + Out << ' '; + WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context); +} + void AssemblyWriter::init() { if (!TheModule) return; @@ -1279,6 +2120,9 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, void AssemblyWriter::printModule(const Module *M) { Machine.initialize(); + if (shouldPreserveAssemblyUseListOrder()) + UseListOrders = predictUseListOrder(M); + if (!M->getModuleIdentifier().empty() && // Don't print the ID if it will start a new line (which would // require a comment char before it). @@ -1339,9 +2183,13 @@ void AssemblyWriter::printModule(const Module *M) { I != E; ++I) printAlias(I); + // Output global use-lists. + printUseLists(nullptr); + // Output all of the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) printFunction(I); + assert(UseListOrders.empty() && "All use-lists should have been consumed"); // Output all attribute groups. if (!Machine.as_empty()) { @@ -1455,6 +2303,24 @@ static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM, } } +static void maybePrintComdat(formatted_raw_ostream &Out, + const GlobalObject &GO) { + const Comdat *C = GO.getComdat(); + if (!C) + return; + + if (isa(GO)) + Out << ','; + Out << " comdat"; + + if (GO.getName() == C->getName()) + return; + + Out << '('; + PrintLLVMName(Out, C->getName(), ComdatPrefix); + Out << ')'; +} + void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->isMaterializable()) Out << "; Materializable\n"; @@ -1488,10 +2354,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintEscapedString(GV->getSection(), Out); Out << '"'; } - if (GV->hasComdat()) { - Out << ", comdat "; - PrintLLVMName(Out, GV->getComdat()->getName(), ComdatPrefix); - } + maybePrintComdat(Out, *GV); if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); @@ -1672,10 +2535,7 @@ void AssemblyWriter::printFunction(const Function *F) { PrintEscapedString(F->getSection(), Out); Out << '"'; } - if (F->hasComdat()) { - Out << " comdat "; - PrintLLVMName(Out, F->getComdat()->getName(), ComdatPrefix); - } + maybePrintComdat(Out, *F); if (F->getAlignment()) Out << " align " << F->getAlignment(); if (F->hasGC()) @@ -1684,6 +2544,11 @@ void AssemblyWriter::printFunction(const Function *F) { Out << " prefix "; writeOperand(F->getPrefixData(), true); } + if (F->hasPrologueData()) { + Out << " prologue "; + writeOperand(F->getPrologueData(), true); + } + if (F->isDeclaration()) { Out << '\n'; } else { @@ -1692,6 +2557,9 @@ void AssemblyWriter::printFunction(const Function *F) { for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I) printBasicBlock(I); + // Output the function's use-lists. + printUseLists(F); + Out << "}\n"; } @@ -1955,6 +2823,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ", "; writeParamOperand(CI->getArgOperand(op), PAL, op + 1); } + + // Emit an ellipsis if this is a musttail call in a vararg function. This + // is only to aid readability, musttail calls forward varargs by default. + if (CI->isMustTailCall() && CI->getParent() && + CI->getParent()->getParent() && + CI->getParent()->getParent()->isVarArg()) + Out << ", ..."; + Out << ')'; if (PAL.hasAttributes(AttributeSet::FunctionIndex)) Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); @@ -2031,6 +2907,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(&I)) { + Out << ' '; + TypePrinter.print(GEP->getSourceElementType(), Out); + Out << ','; + } else if (const auto *LI = dyn_cast(&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 @@ -2087,7 +2972,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } // Print Metadata info. - SmallVector, 4> InstMD; + SmallVector, 4> InstMD; I.getAllMetadata(InstMD); if (!InstMD.empty()) { SmallVector MDNames; @@ -2107,32 +2992,10 @@ void AssemblyWriter::printInstruction(const Instruction &I) { printInfoComment(I); } -static void WriteMDNodeComment(const MDNode *Node, - formatted_raw_ostream &Out) { - if (Node->getNumOperands() < 1) - return; - - Value *Op = Node->getOperand(0); - if (!Op || !isa(Op) || cast(Op)->getBitWidth() < 32) - return; - - DIDescriptor Desc(Node); - if (!Desc.Verify()) - return; - - 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 ]"; - } -} - void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) { - Out << '!' << Slot << " = metadata "; + Out << '!' << Slot << " = "; printMDNodeBody(Node); + Out << "\n"; } void AssemblyWriter::writeAllMDNodes() { @@ -2149,8 +3012,6 @@ void AssemblyWriter::writeAllMDNodes() { void AssemblyWriter::printMDNodeBody(const MDNode *Node) { WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule); - WriteMDNodeComment(Node, Out); - Out << "\n"; } void AssemblyWriter::writeAllAttributeGroups() { @@ -2169,6 +3030,45 @@ void AssemblyWriter::writeAllAttributeGroups() { } // namespace llvm +void AssemblyWriter::printUseListOrder(const UseListOrder &Order) { + bool IsInFunction = Machine.getFunction(); + if (IsInFunction) + Out << " "; + + Out << "uselistorder"; + if (const BasicBlock *BB = + IsInFunction ? nullptr : dyn_cast(Order.V)) { + Out << "_bb "; + writeOperand(BB->getParent(), false); + Out << ", "; + writeOperand(BB, false); + } else { + Out << " "; + writeOperand(Order.V, true); + } + Out << ", { "; + + assert(Order.Shuffle.size() >= 2 && "Shuffle too small"); + Out << Order.Shuffle[0]; + for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I) + Out << ", " << Order.Shuffle[I]; + Out << " }\n"; +} + +void AssemblyWriter::printUseLists(const Function *F) { + auto hasMore = + [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; }; + if (!hasMore()) + // Nothing to do. + return; + + Out << "\n; uselistorder directives\n"; + while (hasMore()) { + printUseListOrder(UseListOrders.back()); + UseListOrders.pop_back(); + } +} + //===----------------------------------------------------------------------===// // External Interface declarations //===----------------------------------------------------------------------===// @@ -2244,18 +3144,14 @@ void Value::print(raw_ostream &ROS) const { W.printFunction(F); else W.printAlias(cast(GV)); - } else if (const MDNode *N = dyn_cast(this)) { - const Function *F = N->getFunction(); - SlotTracker SlotTable(F); - AssemblyWriter W(OS, SlotTable, F ? F->getParent() : nullptr, nullptr); - W.printMDNodeBody(N); + } else if (const MetadataAsValue *V = dyn_cast(this)) { + V->getMetadata()->print(ROS); } else if (const Constant *C = dyn_cast(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); OS << ' '; WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr); - } else if (isa(this) || isa(this) || - isa(this)) { + } else if (isa(this) || isa(this)) { this->printAsOperand(OS); } else { llvm_unreachable("Unknown value to print out!"); @@ -2265,9 +3161,8 @@ 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(this) && !isa(this)) || - hasName() || isa(this))) { + if (!PrintType && ((!isa(this) && !isa(this)) || + hasName() || isa(this))) { WriteAsOperandInternal(O, this, nullptr, nullptr, M); return; } @@ -2286,17 +3181,54 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) cons WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M); } +void Metadata::print(raw_ostream &ROS) const { + formatted_raw_ostream OS(ROS); + if (auto *N = dyn_cast(this)) { + SlotTracker SlotTable(static_cast(nullptr)); + AssemblyWriter W(OS, SlotTable, nullptr, nullptr); + W.printMDNodeBody(N); + + return; + } + printAsOperand(OS); +} + +void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType, + const Module *M) const { + formatted_raw_ostream OS(ROS); + + std::unique_ptr TypePrinter; + if (PrintType) { + TypePrinter.reset(new TypePrinting); + if (M) + TypePrinter->incorporateTypes(*M); + } + WriteAsOperandInternal(OS, this, TypePrinter.get(), nullptr, M, + /* FromValue */ true); +} + // 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()); } + +LLVM_DUMP_METHOD +void Metadata::dump() const { + print(dbgs()); + dbgs() << '\n'; +}