diff options
Diffstat (limited to 'lib/IR/AsmWriter.cpp')
-rw-r--r-- | lib/IR/AsmWriter.cpp | 975 |
1 files changed, 488 insertions, 487 deletions
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index de0e614..ae0beba 100644 --- a/lib/IR/AsmWriter.cpp +++ b/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" @@ -32,12 +32,14 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Operator.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; @@ -275,6 +277,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 +389,29 @@ 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() {} + ~TypePrinting() {} + + 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 +541,7 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) { OS << '>'; } +namespace { //===----------------------------------------------------------------------===// // SlotTracker Class: Enumerate slot numbers for unnamed values //===----------------------------------------------------------------------===// @@ -525,6 +559,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 +577,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 +651,18 @@ private: /// Add all of the functions arguments, basic blocks, and instructions. void processFunction(); + /// 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 +697,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) { @@ -692,6 +747,9 @@ void SlotTracker::processModule() { // Add all the unnamed functions to the table. CreateModuleSlot(I); + if (ShouldInitializeAllMetadata) + processFunctionMetadata(*I); + // Add all the function attributes to the table. // FIXME: Add attributes of other objects? AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); @@ -715,46 +773,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); + + for (auto &I : BB) { + if (!I.getType()->isVoidTy() && !I.hasName()) + CreateFunctionSlot(&I); + + processInstructionMetadata(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 +805,29 @@ void SlotTracker::processFunction() { ST_DEBUG("end processFunction!\n"); } +void SlotTracker::processFunctionMetadata(const Function &F) { + for (auto &BB : F) + 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 +1075,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 +1288,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 << ' '; @@ -1285,8 +1358,52 @@ raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) { } 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 DebugNode *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 +void MDFieldPrinter::printTag(const DebugNode *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, @@ -1298,27 +1415,68 @@ static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD, 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; +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 = DIDescriptor::splitFlags(Flags, SplitFlags); + + FieldSeparator FlagsFS(" | "); + for (unsigned F : SplitFlags) { + const char *StringF = DIDescriptor::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 << N->getTag(); + Out << Value; } static void writeGenericDebugNode(raw_ostream &Out, const GenericDebugNode *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!GenericDebugNode("; - FieldSeparator FS; - writeTag(Out, FS, N); - if (!N->getHeader().empty()) { - Out << FS << "header: \""; - PrintEscapedString(N->getHeader(), Out); - Out << "\""; - } + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("header", N->getHeader()); if (N->getNumDwarfOperands()) { - Out << FS << "operands: {"; + Out << Printer.FS << "operands: {"; FieldSeparator IFS; for (auto &I : N->dwarf_operands()) { Out << IFS; @@ -1333,111 +1491,64 @@ static void writeMDLocation(raw_ostream &Out, const MDLocation *DL, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDLocation("; - FieldSeparator FS; + 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 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(); + MDFieldPrinter Printer(Out); + Printer.printInt("count", N->getCount(), /* ShouldSkipZero */ false); + Printer.printInt("lowerBound", N->getLo()); Out << ")"; } static void writeMDEnumerator(raw_ostream &Out, const MDEnumerator *N, TypePrinting *, SlotTracker *, const Module *) { Out << "!MDEnumerator("; - FieldSeparator FS; - Out << FS << "name: \"" << N->getName() << "\""; - Out << FS << "value: " << N->getValue(); + MDFieldPrinter Printer(Out); + Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false); + Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false); Out << ")"; } static void writeMDBasicType(raw_ostream &Out, const MDBasicType *N, TypePrinting *, SlotTracker *, const Module *) { Out << "!MDBasicType("; - FieldSeparator FS; - writeTag(Out, FS, N); - if (!N->getName().empty()) - 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; - } + 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 writeDIFlags(raw_ostream &Out, unsigned Flags) { - SmallVector<unsigned, 8> 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); - if (!N->getName().empty()) - 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(); - if (N->getScope()) { - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - } - 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); - } + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getScope()); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("baseType", N->getBaseType(), + /* 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->getExtraData()); Out << ")"; } @@ -1445,61 +1556,23 @@ static void writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDCompositeType("; - FieldSeparator FS; - writeTag(Out, FS, N); - if (!N->getName().empty()) - 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(); - if (N->getScope()) { - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - } - 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); - } - if (!N->getIdentifier().empty()) - Out << FS << "identifier: \"" << N->getIdentifier() << "\""; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getScope()); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("baseType", N->getBaseType()); + Printer.printInt("size", N->getSizeInBits()); + Printer.printInt("align", N->getAlignInBits()); + Printer.printInt("offset", N->getOffsetInBits()); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("elements", N->getElements()); + Printer.printDwarfEnum("runtimeLang", N->getRuntimeLang(), + dwarf::LanguageString); + Printer.printMetadata("vtableHolder", N->getVTableHolder()); + Printer.printMetadata("templateParams", N->getTemplateParams()); + Printer.printString("identifier", N->getIdentifier()); Out << ")"; } @@ -1507,22 +1580,20 @@ 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); + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("types", N->getTypeArray(), /* ShouldSkipNull */ false); Out << ")"; } static void writeMDFile(raw_ostream &Out, const MDFile *N, TypePrinting *, SlotTracker *, const Module *) { Out << "!MDFile("; - FieldSeparator FS; - Out << FS << "filename: \"" << N->getFilename() << "\""; - Out << FS << "directory: \"" << N->getDirectory() << "\""; + MDFieldPrinter Printer(Out); + Printer.printString("filename", N->getFilename(), + /* ShouldSkipEmpty */ false); + Printer.printString("directory", N->getDirectory(), + /* ShouldSkipEmpty */ false); Out << ")"; } @@ -1530,48 +1601,23 @@ 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); - if (!N->getProducer().empty()) - Out << FS << "producer: \"" << N->getProducer() << "\""; - Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false"); - if (!N->getFlags().empty()) - Out << FS << "flags: \"" << N->getFlags() << "\""; - Out << FS << "runtimeVersion: " << N->getRuntimeVersion(); - if (!N->getSplitDebugFilename().empty()) - 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); - } + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printDwarfEnum("language", N->getSourceLanguage(), + dwarf::LanguageString, /* ShouldSkipZero */ false); + Printer.printMetadata("file", N->getFile(), /* 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->getEnumTypes()); + Printer.printMetadata("retainedTypes", N->getRetainedTypes()); + Printer.printMetadata("subprograms", N->getSubprograms()); + Printer.printMetadata("globals", N->getGlobalVariables()); + Printer.printMetadata("imports", N->getImportedEntities()); Out << ")"; } @@ -1579,67 +1625,26 @@ static void writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDSubprogram("; - FieldSeparator FS; - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - Out << FS << "name: \"" << N->getName() << "\""; - if (!N->getLinkageName().empty()) - Out << FS << "linkageName: \"" << N->getLinkageName() << "\""; - 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); - } + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printString("linkageName", N->getLinkageName()); + Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("type", N->getType()); + Printer.printBool("isLocal", N->isLocalToUnit()); + Printer.printBool("isDefinition", N->isDefinition()); + Printer.printInt("scopeLine", N->getScopeLine()); + Printer.printMetadata("containingType", N->getContainingType()); + 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->getFunction()); + Printer.printMetadata("templateParams", N->getTemplateParams()); + Printer.printMetadata("declaration", N->getDeclaration()); + Printer.printMetadata("variables", N->getVariables()); Out << ")"; } @@ -1647,18 +1652,11 @@ 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(); + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printInt("column", N->getColumn()); Out << ")"; } @@ -1668,15 +1666,11 @@ static void writeMDLexicalBlockFile(raw_ostream &Out, 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(); + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("discriminator", N->getDiscriminator(), + /* ShouldSkipZero */ false); Out << ")"; } @@ -1684,17 +1678,11 @@ static void writeMDNamespace(raw_ostream &Out, const MDNamespace *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDNamespace("; - 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->getName().empty()) - Out << FS << "name: \"" << N->getName() << "\""; - if (N->getLine()) - Out << FS << "line: " << N->getLine(); + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); Out << ")"; } @@ -1704,10 +1692,9 @@ static void writeMDTemplateTypeParameter(raw_ostream &Out, SlotTracker *Machine, const Module *Context) { Out << "!MDTemplateTypeParameter("; - FieldSeparator FS; - Out << FS << "name: \"" << N->getName() << "\""; - Out << FS << "type: "; - writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("type", N->getType(), /* ShouldSkipNull */ false); Out << ")"; } @@ -1717,13 +1704,12 @@ static void writeMDTemplateValueParameter(raw_ostream &Out, SlotTracker *Machine, const Module *Context) { Out << "!MDTemplateValueParameter("; - FieldSeparator FS; - writeTag(Out, FS, N); - Out << FS << "name: \"" << N->getName() << "\""; - Out << FS << "type: "; - writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context); - Out << FS << "value: "; - writeMetadataAsOperand(Out, N->getValue(), TypePrinter, Machine, Context); + 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->getType()); + Printer.printMetadata("value", N->getValue(), /* ShouldSkipNull */ false); Out << ")"; } @@ -1731,36 +1717,17 @@ static void writeMDGlobalVariable(raw_ostream &Out, const MDGlobalVariable *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDGlobalVariable("; - FieldSeparator FS; - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - Out << FS << "name: \"" << N->getName() << "\""; - if (!N->getLinkageName().empty()) - Out << FS << "linkageName: \"" << N->getLinkageName() << "\""; - 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); - } + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printString("linkageName", N->getLinkageName()); + Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("type", N->getType()); + Printer.printBool("isLocal", N->isLocalToUnit()); + Printer.printBool("isDefinition", N->isDefinition()); + Printer.printMetadata("variable", N->getVariable()); + Printer.printMetadata("declaration", N->getStaticDataMemberDeclaration()); Out << ")"; } @@ -1768,34 +1735,18 @@ static void writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDLocalVariable("; - FieldSeparator FS; - writeTag(Out, FS, N); - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - 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(); - if (N->getType()) { - Out << FS << "type: "; - writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, - Context); - } - if (N->getTag() == dwarf::DW_TAG_arg_variable || N->getArg()) - Out << FS << "arg: " << N->getArg(); - if (auto Flags = N->getFlags()) { - Out << FS << "flags: "; - writeDIFlags(Out, Flags); - } - if (N->getInlinedAt()) { - Out << FS << "inlinedAt: "; - writeMetadataAsOperand(Out, N->getInlinedAt(), TypePrinter, Machine, - Context); - } + 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->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("type", N->getType()); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("inlinedAt", N->getInlinedAt()); Out << ")"; } @@ -1824,24 +1775,14 @@ static void writeMDObjCProperty(raw_ostream &Out, const MDObjCProperty *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDObjCProperty("; - FieldSeparator FS; - 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(); - if (!N->getSetterName().empty()) - Out << FS << "setter: \"" << N->getSetterName() << "\""; - if (!N->getGetterName().empty()) - 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); - } + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("file", N->getFile()); + Printer.printInt("line", N->getLine()); + Printer.printString("setter", N->getSetterName()); + Printer.printString("getter", N->getGetterName()); + Printer.printInt("attributes", N->getAttributes()); + Printer.printMetadata("type", N->getType()); Out << ")"; } @@ -1849,17 +1790,12 @@ static void writeMDImportedEntity(raw_ostream &Out, const MDImportedEntity *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Out << "!MDImportedEntity("; - FieldSeparator FS; - writeTag(Out, FS, N); - 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 << FS << "name: \"" << N->getName() << "\""; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printTag(N); + Printer.printString("name", N->getName()); + Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("entity", N->getEntity()); + Printer.printInt("line", N->getLine()); Out << ")"; } @@ -1868,10 +1804,10 @@ 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 "; + else if (Node->isTemporary()) + Out << "<temporary!> "; // Handle broken code. switch (Node->getMetadataID()) { default: @@ -1998,6 +1934,64 @@ 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; + 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); + + 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 + void AssemblyWriter::init() { if (!TheModule) return; @@ -2025,8 +2019,6 @@ AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, const Module *M, init(); } -AssemblyWriter::~AssemblyWriter() { } - void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { if (!Operand) { Out << "<null operand!>"; @@ -2876,7 +2868,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); } @@ -2898,6 +2896,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 @@ -2974,29 +2981,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) { 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)) - 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 << " = "; printMDNodeBody(Node); @@ -3017,7 +3001,6 @@ void AssemblyWriter::writeAllMDNodes() { void AssemblyWriter::printMDNodeBody(const MDNode *Node) { WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule); - WriteMDNodeComment(Node, Out); } void AssemblyWriter::writeAllAttributeGroups() { @@ -3034,8 +3017,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) @@ -3130,11 +3111,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)) { @@ -3142,7 +3136,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); @@ -3151,7 +3146,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); @@ -3167,8 +3162,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; } @@ -3184,33 +3180,35 @@ 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. @@ -3234,7 +3232,10 @@ LLVM_DUMP_METHOD void NamedMDNode::dump() const { print(dbgs()); } LLVM_DUMP_METHOD -void Metadata::dump() const { - print(dbgs()); +void Metadata::dump() const { dump(nullptr); } + +LLVM_DUMP_METHOD +void Metadata::dump(const Module *M) const { + print(dbgs(), M); dbgs() << '\n'; } |