X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FIR%2FAsmWriter.cpp;h=9018180ad75a3d9a6fc7f2f7b884dc5ea0cd936c;hp=6248f3e7c3caa9bf8220e83aab08dc69eeb5d8e1;hb=0552dc73a4cbcd3934db1b0560f163f0b1e487f4;hpb=6a390dc584bf705d9650fa3b4eb2675030e39e81 diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 6248f3e7c3c..9018180ad75 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" @@ -30,14 +30,18 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSlotTracker.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 #include using namespace llvm; @@ -106,6 +110,10 @@ static OrderMap orderModule(const Module *M) { if (!isa(F.getPrologueData())) orderValue(F.getPrologueData(), OM); + if (F.hasPersonalityFn()) + if (!isa(F.getPersonalityFn())) + orderValue(F.getPersonalityFn(), OM); + orderValue(&F, OM); if (F.isDeclaration()) @@ -224,8 +232,7 @@ static UseListOrderStack predictUseListOrder(const Module *M) { // 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; + for (const Function &F : make_range(M->rbegin(), M->rend())) { if (F.isDeclaration()) continue; for (const BasicBlock &BB : F) @@ -275,6 +282,15 @@ static const Module *getModuleFromVal(const Value *V) { if (const GlobalValue *GV = dyn_cast(V)) return GV->getParent(); + + if (const auto *MAV = dyn_cast(V)) { + for (const User *U : MAV->users()) + if (isa(U)) + if (const Module *M = getModuleFromVal(U)) + return M; + return nullptr; + } + return nullptr; } @@ -326,18 +342,8 @@ enum PrefixType { NoPrefix }; -/// PrintLLVMName - Turn the specified name into an 'LLVM name', which is either -/// prefixed with % (if the string only contains simple characters) or is -/// surrounded with ""'s (if it has special chars in it). Print it out. -static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { +void llvm::printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name) { assert(!Name.empty() && "Cannot get empty name!"); - switch (Prefix) { - case NoPrefix: break; - case GlobalPrefix: OS << '@'; break; - case ComdatPrefix: OS << '$'; break; - case LabelPrefix: break; - case LocalPrefix: OS << '%'; break; - } // Scan the name to see if it needs quotes first. bool NeedsQuotes = isdigit(static_cast(Name[0])); @@ -369,16 +375,58 @@ static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { OS << '"'; } -/// PrintLLVMName - Turn the specified name into an 'LLVM name', which is either -/// prefixed with % (if the string only contains simple characters) or is -/// surrounded with ""'s (if it has special chars in it). Print it out. +/// Turn the specified name into an 'LLVM name', which is either prefixed with % +/// (if the string only contains simple characters) or is surrounded with ""'s +/// (if it has special chars in it). Print it out. +static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { + switch (Prefix) { + case NoPrefix: + break; + case GlobalPrefix: + OS << '@'; + break; + case ComdatPrefix: + OS << '$'; + break; + case LabelPrefix: + break; + case LocalPrefix: + OS << '%'; + break; + } + printLLVMNameWithoutPrefix(OS, Name); +} + +/// Turn the specified name into an 'LLVM name', which is either prefixed with % +/// (if the string only contains simple characters) or is surrounded with ""'s +/// (if it has special chars in it). Print it out. static void PrintLLVMName(raw_ostream &OS, const Value *V) { PrintLLVMName(OS, V->getName(), isa(V) ? GlobalPrefix : LocalPrefix); } -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 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 +556,7 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) { OS << '>'; } +namespace llvm { //===----------------------------------------------------------------------===// // SlotTracker Class: Enumerate slot numbers for unnamed values //===----------------------------------------------------------------------===// @@ -525,6 +574,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 +592,20 @@ private: DenseMap 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 +666,48 @@ 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 llvm + +ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M, + const Function *F) + : M(M), F(F), Machine(&Machine) {} + +ModuleSlotTracker::ModuleSlotTracker(const Module *M, + bool ShouldInitializeAllMetadata) + : MachineStorage(M ? new SlotTracker(M, ShouldInitializeAllMetadata) + : nullptr), + M(M), Machine(MachineStorage.get()) {} + +ModuleSlotTracker::~ModuleSlotTracker() {} + +void ModuleSlotTracker::incorporateFunction(const Function &F) { + if (!Machine) + return; -SlotTracker *createSlotTracker(const Module *M) { + // Nothing to do if this is the right function already. + if (this->F == &F) + return; + if (this->F) + Machine->purgeFunction(); + Machine->incorporateFunction(&F); + this->F = &F; +} + +int ModuleSlotTracker::getLocalSlot(const Value *V) { + assert(F && "No function incorporated"); + return Machine->getLocalSlot(V); +} + +static SlotTracker *createSlotTracker(const Module *M) { return new SlotTracker(M); } @@ -645,15 +742,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 +771,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 +818,30 @@ void SlotTracker::processFunction() { ST_DEBUG("Inserting Instructions:\n"); - SmallVector, 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(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(I->getOperand(i))) - if (MDNode *N = dyn_cast(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(&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(I)) { + } else if (const InvokeInst *II = dyn_cast(&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 +850,35 @@ void SlotTracker::processFunction() { ST_DEBUG("end processFunction!\n"); } +void SlotTracker::processFunctionMetadata(const Function &F) { + SmallVector, 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(&I)) + if (Function *F = CI->getCalledFunction()) + if (F->isIntrinsic()) + for (auto &Op : I.operands()) + if (auto *V = dyn_cast_or_null(Op)) + if (MDNode *N = dyn_cast(V->getMetadata())) + CreateMetadataSlot(N); + + // Process metadata attached to this instruction. + SmallVector, 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 +1126,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 +1339,11 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << ' ' << getPredicateText(CE->getPredicate()); Out << " ("; + if (const GEPOperator *GEP = dyn_cast(CE)) { + TypePrinter.print(GEP->getSourceElementType(), Out); + Out << ", "; + } + for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) { TypePrinter.print((*OI)->getType(), Out); Out << ' '; @@ -1275,17 +1396,62 @@ 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 + void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true); + void printBool(StringRef Name, bool Value); + void printDIFlags(StringRef Name, unsigned Flags); + template + void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString, + bool ShouldSkipZero = true); +}; } // end namespace +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, @@ -1297,27 +1463,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; - else - Out << N->getTag(); +void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD, + bool ShouldSkipNull) { + if (ShouldSkipNull && !MD) + return; + + Out << FS << Name << ": "; + writeMetadataAsOperand(Out, MD, TypePrinter, Machine, Context); } -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 << "\""; +template +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 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 +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 << FS << "operands: {"; + Out << Printer.FS << "operands: {"; FieldSeparator IFS; for (auto &I : N->dwarf_operands()) { Out << IFS; @@ -1328,463 +1535,288 @@ static void writeGenericDebugNode(raw_ostream &Out, const GenericDebugNode *N, Out << ")"; } -static void writeMDLocation(raw_ostream &Out, const MDLocation *DL, +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 writeMDSubrange(raw_ostream &Out, const MDSubrange *N, +static void writeDISubrange(raw_ostream &Out, const DISubrange *N, TypePrinting *, SlotTracker *, const Module *) { - Out << "!MDSubrange("; - FieldSeparator FS; - Out << FS << "count: " << N->getCount(); - if (N->getLo()) - Out << FS << "lowerBound: " << N->getLo(); + Out << "!DISubrange("; + MDFieldPrinter Printer(Out); + Printer.printInt("count", N->getCount(), /* ShouldSkipZero */ false); + Printer.printInt("lowerBound", N->getLowerBound()); Out << ")"; } -static void writeMDEnumerator(raw_ostream &Out, const MDEnumerator *N, +static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N, TypePrinting *, SlotTracker *, const Module *) { - Out << "!MDEnumerator("; - FieldSeparator FS; - Out << FS << "value: " << N->getValue(); - Out << FS << "name: \"" << N->getName() << "\""; + Out << "!DIEnumerator("; + 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, +static void writeDIBasicType(raw_ostream &Out, const DIBasicType *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; - } + 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 writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N, +static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *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 (N->getFlags()) - Out << FS << "flags: " << N->getFlags(); - if (N->getExtraData()) { - Out << FS << "extraData: "; - writeMetadataAsOperand(Out, N->getExtraData(), TypePrinter, Machine, - 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 writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N, +static void writeDICompositeType(raw_ostream &Out, const DICompositeType *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 (N->getFlags()) - Out << FS << "flags: " << N->getFlags(); - 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() << "\""; + 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 writeMDSubroutineType(raw_ostream &Out, const MDSubroutineType *N, +static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { - Out << "!MDSubroutineType("; - FieldSeparator FS; - if (N->getFlags()) - Out << FS << "flags: " << N->getFlags(); - Out << FS << "types: "; - writeMetadataAsOperand(Out, N->getTypeArray(), TypePrinter, Machine, Context); + Out << "!DISubroutineType("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printDIFlags("flags", N->getFlags()); + Printer.printMetadata("types", N->getRawTypeArray(), + /* ShouldSkipNull */ false); Out << ")"; } -static void writeMDFile(raw_ostream &Out, const MDFile *N, TypePrinting *, +static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *, SlotTracker *, const Module *) { - Out << "!MDFile("; - FieldSeparator FS; - Out << FS << "filename: \"" << N->getFilename() << "\""; - Out << FS << "directory: \"" << N->getDirectory() << "\""; + Out << "!DIFile("; + MDFieldPrinter Printer(Out); + Printer.printString("filename", N->getFilename(), + /* ShouldSkipEmpty */ false); + Printer.printString("directory", N->getDirectory(), + /* ShouldSkipEmpty */ false); Out << ")"; } -static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N, +static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *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(); - if (N->getFile()) { - 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); - } + 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 writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N, +static void writeDISubprogram(raw_ostream &Out, const DISubprogram *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 (N->getFlags()) - Out << FS << "flags: " << N->getFlags(); - 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 << "!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 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(); +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 writeMDLexicalBlockFile(raw_ostream &Out, - const MDLexicalBlockFile *N, +static void writeDILexicalBlockFile(raw_ostream &Out, + const DILexicalBlockFile *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 << "!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 writeMDNamespace(raw_ostream &Out, const MDNamespace *N, +static void writeDINamespace(raw_ostream &Out, const DINamespace *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(); + 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 writeMDTemplateTypeParameter(raw_ostream &Out, - const MDTemplateTypeParameter *N, +static void writeDIModule(raw_ostream &Out, const DIModule *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DIModule("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printString("name", N->getName()); + Printer.printString("configMacros", N->getConfigurationMacros()); + Printer.printString("includePath", N->getIncludePath()); + Printer.printString("isysroot", N->getISysRoot()); + Out << ")"; +} + + +static void writeDITemplateTypeParameter(raw_ostream &Out, + const DITemplateTypeParameter *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { - Out << "!MDTemplateTypeParameter("; - FieldSeparator FS; - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - Out << FS << "name: \"" << N->getName() << "\""; - Out << FS << "type: "; - writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context); + Out << "!DITemplateTypeParameter("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printString("name", N->getName()); + Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false); Out << ")"; } -static void writeMDTemplateValueParameter(raw_ostream &Out, - const MDTemplateValueParameter *N, +static void writeDITemplateValueParameter(raw_ostream &Out, + const DITemplateValueParameter *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { - Out << "!MDTemplateValueParameter("; - FieldSeparator FS; - writeTag(Out, FS, N); - Out << FS << "scope: "; - writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); - 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); + 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 writeMDGlobalVariable(raw_ostream &Out, const MDGlobalVariable *N, +static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *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); - } + 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 writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N, +static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *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 (N->getFlags()) - Out << FS << "flags: " << N->getFlags(); - if (N->getInlinedAt()) { - Out << FS << "inlinedAt: "; - writeMetadataAsOperand(Out, N->getInlinedAt(), TypePrinter, Machine, - 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 writeMDExpression(raw_ostream &Out, const MDExpression *N, +static void writeDIExpression(raw_ostream &Out, const DIExpression *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { - Out << "!MDExpression("; + Out << "!DIExpression("; FieldSeparator FS; if (N->isValid()) { for (auto I = N->expr_op_begin(), E = N->expr_op_end(); I != E; ++I) { @@ -1802,46 +1834,31 @@ static void writeMDExpression(raw_ostream &Out, const MDExpression *N, Out << ")"; } -static void writeMDObjCProperty(raw_ostream &Out, const MDObjCProperty *N, +static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *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); - } + 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 writeMDImportedEntity(raw_ostream &Out, const MDImportedEntity *N, +static void writeDIImportedEntity(raw_ostream &Out, const DIImportedEntity *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() << "\""; + 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 << ")"; } @@ -1850,10 +1867,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 << " "; // Handle broken code. switch (Node->getMetadataID()) { default: @@ -1951,8 +1968,11 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, SlotTracker *Machine, const Module *Context, bool FromValue) { if (const MDNode *N = dyn_cast(MD)) { - if (!Machine) - Machine = new SlotTracker(Context); + std::unique_ptr MachineStorage; + if (!Machine) { + MachineStorage = make_unique(Context); + Machine = MachineStorage.get(); + } int Slot = Machine->getMetadataSlot(N); if (Slot == -1) // Give the pointer value instead of "badref", since this comes up all @@ -1980,6 +2000,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 SlotTrackerStorage; + SlotTracker &Machine; + TypePrinting TypePrinter; + AssemblyAnnotationWriter *AnnotationWriter; + SetVector Comdats; + bool ShouldPreserveUseListOrder; + UseListOrderStack UseListOrders; + SmallVector 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> &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; @@ -1992,23 +2083,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), SlotTrackerStorage(createSlotTracker(M)), + Machine(*SlotTrackerStorage), AnnotationWriter(AAW), + ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) { init(); } -AssemblyWriter::~AssemblyWriter() { } - void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { if (!Operand) { Out << ""; @@ -2093,7 +2184,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() && @@ -2109,27 +2200,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(); @@ -2145,23 +2229,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. @@ -2173,9 +2255,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()) { @@ -2184,15 +2265,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 << " "; } else { - if (isalpha(static_cast(Name[0])) || - Name[0] == '-' || Name[0] == '$' || - Name[0] == '.' || Name[0] == '_') + if (isalpha(static_cast(Name[0])) || Name[0] == '-' || + Name[0] == '$' || Name[0] == '.' || Name[0] == '_') Out << Name[0]; else Out << '\\' << hexdigit(Name[0] >> 4) << hexdigit(Name[0] & 0x0F); @@ -2205,9 +2284,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 << ""; @@ -2217,7 +2302,6 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { Out << "}\n"; } - static void PrintLinkage(GlobalValue::LinkageTypes LT, formatted_raw_ostream &Out) { switch (LT) { @@ -2237,7 +2321,6 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT, } } - static void PrintVisibility(GlobalValue::VisibilityTypes Vis, formatted_raw_ostream &Out) { switch (Vis) { @@ -2338,13 +2421,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 << "<> = "; - 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); @@ -2521,6 +2600,14 @@ void AssemblyWriter::printFunction(const Function *F) { Out << " prologue "; writeOperand(F->getPrologueData(), true); } + if (F->hasPersonalityFn()) { + Out << " personality "; + writeOperand(F->getPersonalityFn(), /*PrintType=*/true); + } + + SmallVector, 4> MDs; + F->getAllMetadata(MDs); + printMetadataAttachments(MDs, " "); if (F->isDeclaration()) { Out << '\n'; @@ -2613,10 +2700,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(&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); } @@ -2743,8 +2846,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } else if (const LandingPadInst *LPI = dyn_cast(&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"; @@ -2768,8 +2871,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } Operand = CI->getCalledValue(); - PointerType *PTy = cast(Operand->getType()); - FunctionType *FTy = cast(PTy->getElementType()); + FunctionType *FTy = cast(CI->getFunctionType()); Type *RetTy = FTy->getReturnType(); const AttributeSet &PAL = CI->getAttributes(); @@ -2781,15 +2883,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(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) @@ -2809,8 +2905,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); } else if (const InvokeInst *II = dyn_cast(&I)) { Operand = II->getCalledValue(); - PointerType *PTy = cast(Operand->getType()); - FunctionType *FTy = cast(PTy->getElementType()); + FunctionType *FTy = cast(II->getFunctionType()); Type *RetTy = FTy->getReturnType(); const AttributeSet &PAL = II->getAttributes(); @@ -2828,15 +2923,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(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) @@ -2858,7 +2947,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); } @@ -2880,6 +2975,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 @@ -2938,50 +3042,38 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // Print Metadata info. SmallVector, 4> InstMD; I.getAllMetadata(InstMD); - if (!InstMD.empty()) { - SmallVector 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 << ", !"; - } - 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) +void AssemblyWriter::printMetadataAttachments( + const SmallVectorImpl> &MDs, + StringRef Separator) { + if (MDs.empty()) return; - Metadata *Op = Node->getOperand(0); - if (!Op || !isa(Op)) - 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 << "!"; + 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() { @@ -2998,8 +3090,6 @@ void AssemblyWriter::writeAllMDNodes() { void AssemblyWriter::printMDNodeBody(const MDNode *Node) { WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule); - WriteMDNodeComment(Node, Out); - Out << "\n"; } void AssemblyWriter::writeAllAttributeGroups() { @@ -3016,8 +3106,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) @@ -3061,10 +3149,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); } @@ -3112,19 +3208,47 @@ void Type::print(raw_ostream &OS) const { } } +static bool isReferencingMDNode(const Instruction &I) { + if (const auto *CI = dyn_cast(&I)) + if (Function *F = CI->getCalledFunction()) + if (F->isIntrinsic()) + for (auto &Op : I.operands()) + if (auto *V = dyn_cast_or_null(Op)) + if (isa(V->getMetadata())) + return true; + return false; +} + void Value::print(raw_ostream &ROS) const { + bool ShouldInitializeAllMetadata = false; + if (auto *I = dyn_cast(this)) + ShouldInitializeAllMetadata = isReferencingMDNode(*I); + else if (isa(this) || isa(this)) + ShouldInitializeAllMetadata = true; + + ModuleSlotTracker MST(getModuleFromVal(this), ShouldInitializeAllMetadata); + print(ROS, MST); +} + +void Value::print(raw_ostream &ROS, ModuleSlotTracker &MST) const { formatted_raw_ostream OS(ROS); + SlotTracker EmptySlotTable(static_cast(nullptr)); + SlotTracker &SlotTable = + MST.getMachine() ? *MST.getMachine() : EmptySlotTable; + auto incorporateFunction = [&](const Function *F) { + if (F) + MST.incorporateFunction(*F); + }; + if (const Instruction *I = dyn_cast(this)) { - const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr; - SlotTracker SlotTable(F); + incorporateFunction(I->getParent() ? I->getParent()->getParent() : nullptr); AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr); W.printInstruction(*I); } else if (const BasicBlock *BB = dyn_cast(this)) { - SlotTracker SlotTable(BB->getParent()); + incorporateFunction(BB->getParent()); AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr); W.printBasicBlock(BB); } else if (const GlobalValue *GV = dyn_cast(this)) { - SlotTracker SlotTable(GV->getParent()); AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr); if (const GlobalVariable *V = dyn_cast(GV)) W.printGlobal(V); @@ -3133,84 +3257,135 @@ void Value::print(raw_ostream &ROS) const { else W.printAlias(cast(GV)); } else if (const MetadataAsValue *V = dyn_cast(this)) { - V->getMetadata()->print(ROS); + V->getMetadata()->print(ROS, MST, getModuleFromVal(V)); } else if (const Constant *C = dyn_cast(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); OS << ' '; - WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr); + WriteConstantInternal(OS, C, TypePrinter, MST.getMachine(), nullptr); } else if (isa(this) || isa(this)) { - this->printAsOperand(OS); + this->printAsOperand(OS, /* PrintType */ true, MST); } else { llvm_unreachable("Unknown value to print out!"); } } -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))) { - WriteAsOperandInternal(O, this, nullptr, nullptr, M); - return; +/// Print without a type, skipping the TypePrinting object. +/// +/// \return \c true iff printing was succesful. +static bool printWithoutType(const Value &V, raw_ostream &O, + SlotTracker *Machine, const Module *M) { + if (V.hasName() || isa(V) || + (!isa(V) && !isa(V))) { + WriteAsOperandInternal(O, &V, nullptr, Machine, M); + return true; } + return false; +} - if (!M) - M = getModuleFromVal(this); - +static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType, + ModuleSlotTracker &MST) { TypePrinting TypePrinter; - if (M) + if (const Module *M = MST.getModule()) TypePrinter.incorporateTypes(*M); if (PrintType) { - TypePrinter.print(getType(), O); + TypePrinter.print(V.getType(), O); O << ' '; } - WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M); + WriteAsOperandInternal(O, &V, &TypePrinter, MST.getMachine(), + MST.getModule()); } -void Metadata::print(raw_ostream &ROS) const { +void Value::printAsOperand(raw_ostream &O, bool PrintType, + const Module *M) const { + if (!M) + M = getModuleFromVal(this); + + if (!PrintType) + if (printWithoutType(*this, O, nullptr, M)) + return; + + SlotTracker Machine( + M, /* ShouldInitializeAllMetadata */ isa(this)); + ModuleSlotTracker MST(Machine, M); + printAsOperandImpl(*this, O, PrintType, MST); +} + +void Value::printAsOperand(raw_ostream &O, bool PrintType, + ModuleSlotTracker &MST) const { + if (!PrintType) + if (printWithoutType(*this, O, MST.getMachine(), MST.getModule())) + return; + + printAsOperandImpl(*this, O, PrintType, MST); +} + +static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, + ModuleSlotTracker &MST, const Module *M, + bool OnlyAsOperand) { 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); + TypePrinting TypePrinter; + if (M) + TypePrinter.incorporateTypes(*M); + + WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M, + /* FromValue */ true); + + auto *N = dyn_cast(&MD); + if (OnlyAsOperand || !N) return; - } - printAsOperand(OS); + + OS << " = "; + WriteMDNodeBodyInternal(OS, N, &TypePrinter, MST.getMachine(), M); } -void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType, +void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const { + ModuleSlotTracker MST(M, isa(this)); + printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true); +} + +void Metadata::printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST, const Module *M) const { - formatted_raw_ostream OS(ROS); + printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true); +} - std::unique_ptr 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 { + ModuleSlotTracker MST(M, isa(this)); + printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false); +} + +void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST, + const Module *M) const { + printMetadataImpl(OS, *this, MST, 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'; }