Index: include/llvm/BinaryFormat/Dwarf.h =================================================================== --- include/llvm/BinaryFormat/Dwarf.h +++ include/llvm/BinaryFormat/Dwarf.h @@ -24,6 +24,8 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadicDetails.h" namespace llvm { class StringRef; @@ -405,8 +407,8 @@ /// \defgroup DwarfConstantsDumping Dwarf constants dumping functions /// /// All these functions map their argument's value back to the -/// corresponding enumerator name or return nullptr if the value isn't -/// known. +/// corresponding enumerator name or return an empty StringRef if the value +/// isn't known. /// /// @{ StringRef TagString(unsigned Tag); @@ -573,8 +575,32 @@ }; }; +template struct EnumTraits : public std::false_type {}; +template <> struct EnumTraits : public std::true_type { + static constexpr char Type[] = "TAG"; + static constexpr StringRef (*StringFn)(unsigned) = &TagString; +}; + } // End of namespace dwarf +/// Dwarf constants format_provider +/// +/// Specialization of the format_provider template for dwarf enums. Unlike the +/// dumping functions above, these format unknown enumerator values as +/// DW_TYPE_Unknown_1234 (e.g. DW_TAG_Unknown_ffff). +template +struct format_provider< + Enum, typename std::enable_if::value>::type> { + static void format(const Enum &E, raw_ostream &OS, StringRef Style) { + StringRef Str = dwarf::EnumTraits::StringFn(E); + if (Str.empty()) { + OS << "DW_" << dwarf::EnumTraits::Type << "_Unknown_" + << llvm::format("%x", E); + } else + OS << Str; +} +}; + } // End of namespace llvm #endif Index: lib/BinaryFormat/Dwarf.cpp =================================================================== --- lib/BinaryFormat/Dwarf.cpp +++ lib/BinaryFormat/Dwarf.cpp @@ -675,3 +675,5 @@ } return ExtensionsOk; } + +const char llvm::dwarf::EnumTraits::Type[]; Index: lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -16,6 +16,7 @@ #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -126,12 +127,8 @@ } void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { - auto tagString = TagString(getTag()); OS << '[' << getCode() << "] "; - if (!tagString.empty()) - OS << tagString; - else - OS << format("DW_TAG_Unknown_%x", getTag()); + OS << formatv("{0}", getTag()); OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; for (const AttributeSpec &Spec : AttributeSpecs) { OS << '\t'; Index: lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/DJB.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" #include @@ -38,10 +39,6 @@ } } // namespace -static DwarfConstant formatTag(unsigned Tag) { - return {dwarf::TagString, "TAG", Tag}; -} - static DwarfConstant formatForm(unsigned Form) { return {dwarf::FormEncodingString, "FORM", Form}; } @@ -415,7 +412,7 @@ void DWARFDebugNames::Abbrev::dump(ScopedPrinter &W) const { DictScope AbbrevScope(W, ("Abbreviation 0x" + Twine::utohexstr(Code)).str()); - W.startLine() << "Tag: " << formatTag(Tag) << '\n'; + W.startLine() << formatv("Tag: {0}\n", Tag); for (const auto &Attr : Attributes) { W.startLine() << formatIndex(Attr.Index) << ": " << formatForm(Attr.Form) @@ -583,8 +580,7 @@ void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const { W.printHex("Abbrev", Abbr->Code); - W.startLine() << "Tag: " << formatTag(Abbr->Tag) << "\n"; - + W.startLine() << formatv("Tag: {0}\n", Abbr->Tag); assert(Abbr->Attributes.size() == Values.size()); for (const auto &Tuple : zip_first(Abbr->Attributes, Values)) { W.startLine() << formatIndex(std::get<0>(Tuple).Index) << ": "; Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -21,6 +21,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" @@ -465,13 +466,8 @@ if (abbrCode) { auto AbbrevDecl = getAbbreviationDeclarationPtr(); if (AbbrevDecl) { - auto tagString = TagString(getTag()); - if (!tagString.empty()) - WithColor(OS, HighlightColor::Tag).get().indent(Indent) << tagString; - else - WithColor(OS, HighlightColor::Tag).get().indent(Indent) - << format("DW_TAG_Unknown_%x", getTag()); - + WithColor(OS, HighlightColor::Tag).get().indent(Indent) + << formatv("{0}", getTag()); if (DumpOpts.Verbose) OS << format(" [%u] %c", abbrCode, AbbrevDecl->hasChildren() ? '*' : ' '); Index: unittests/BinaryFormat/DwarfTest.cpp =================================================================== --- unittests/BinaryFormat/DwarfTest.cpp +++ unittests/BinaryFormat/DwarfTest.cpp @@ -9,6 +9,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/FormatVariadic.h" #include "gtest/gtest.h" using namespace llvm; @@ -192,4 +193,9 @@ EXPECT_EQ(*RefSize, 8); } +TEST(DwarfTest, format_provider) { + EXPECT_EQ("DW_TAG_compile_unit", formatv("{0}", DW_TAG_compile_unit).str()); + EXPECT_EQ("DW_TAG_Unknown_ffff", formatv("{0}", DW_TAG_hi_user).str()); +} + } // end namespace