+namespace {
+struct FieldSeparator {
+ bool Skip;
+ FieldSeparator() : Skip(true) {}
+};
+raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
+ if (FS.Skip) {
+ FS.Skip = false;
+ return OS;
+ }
+ return OS << ", ";
+}
+} // end namespace
+
+static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ if (!MD) {
+ Out << "null";
+ return;
+ }
+ WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
+}
+
+static void writeTag(raw_ostream &Out, FieldSeparator &FS, const DebugNode *N) {
+ Out << FS << "tag: ";
+ if (const char *Tag = dwarf::TagString(N->getTag()))
+ Out << Tag;
+ else
+ Out << N->getTag();
+}
+
+static void 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 << "\"";
+ }
+ if (N->getNumDwarfOperands()) {
+ Out << FS << "operands: {";
+ FieldSeparator IFS;
+ for (auto &I : N->dwarf_operands()) {
+ Out << IFS;
+ writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context);
+ }
+ Out << "}";
+ }
+ Out << ")";
+}
+
+static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDLocation(";
+ FieldSeparator FS;
+ // Always output the line, since 0 is a relevant and important value for it.
+ Out << FS << "line: " << DL->getLine();
+ if (DL->getColumn())
+ Out << FS << "column: " << DL->getColumn();
+ Out << FS << "scope: ";
+ WriteAsOperandInternal(Out, DL->getScope(), TypePrinter, Machine, Context);
+ if (DL->getInlinedAt()) {
+ Out << FS << "inlinedAt: ";
+ WriteAsOperandInternal(Out, DL->getInlinedAt(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
+static void writeMDSubrange(raw_ostream &Out, const MDSubrange *N,
+ TypePrinting *, SlotTracker *, const Module *) {
+ Out << "!MDSubrange(";
+ FieldSeparator FS;
+ Out << FS << "count: " << N->getCount();
+ if (N->getLo())
+ Out << FS << "lowerBound: " << N->getLo();
+ Out << ")";
+}
+
+static void writeMDEnumerator(raw_ostream &Out, const MDEnumerator *N,
+ TypePrinting *, SlotTracker *, const Module *) {
+ Out << "!MDEnumerator(";
+ FieldSeparator FS;
+ Out << FS << "value: " << N->getValue();
+ Out << FS << "name: \"" << N->getName() << "\"";
+ Out << ")";
+}
+
+static void writeMDBasicType(raw_ostream &, const MDBasicType *, TypePrinting *,
+ SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDDerivedType(raw_ostream &, const MDDerivedType *,
+ TypePrinting *, SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDCompositeType(raw_ostream &, const MDCompositeType *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDSubroutineType(raw_ostream &, const MDSubroutineType *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDFile(raw_ostream &, const MDFile *, TypePrinting *,
+ SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDCompileUnit(raw_ostream &, const MDCompileUnit *,
+ TypePrinting *, SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDSubprogram(raw_ostream &, const MDSubprogram *,
+ TypePrinting *, SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDLexicalBlock(raw_ostream &, const MDLexicalBlock *,
+ TypePrinting *, SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDLexicalBlockFile(raw_ostream &, const MDLexicalBlockFile *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDNamespace(raw_ostream &, const MDNamespace *, TypePrinting *,
+ SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDTemplateTypeParameter(raw_ostream &,
+ const MDTemplateTypeParameter *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDTemplateValueParameter(raw_ostream &,
+ const MDTemplateValueParameter *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDGlobalVariable(raw_ostream &, const MDGlobalVariable *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDLocalVariable(raw_ostream &, const MDLocalVariable *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDExpression(raw_ostream &, const MDExpression *,
+ TypePrinting *, SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDObjCProperty(raw_ostream &, const MDObjCProperty *,
+ TypePrinting *, SlotTracker *, const Module *) {
+ llvm_unreachable("write not implemented");
+}
+static void writeMDImportedEntity(raw_ostream &, const MDImportedEntity *,
+ TypePrinting *, SlotTracker *,
+ const Module *) {
+ llvm_unreachable("write not implemented");
+}
+
+static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ assert(!Node->isTemporary() && "Unexpected forward declaration");
+
+ if (Node->isDistinct())
+ Out << "distinct ";
+
+ switch (Node->getMetadataID()) {
+ default:
+ llvm_unreachable("Expected uniquable MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case Metadata::CLASS##Kind: \
+ write##CLASS(Out, cast<CLASS>(Node), TypePrinter, Machine, Context); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+