[llvm] r328090 - [dwarf] Unify unknown dwarf enum formatting code

Pavel Labath via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 21 04:46:38 PDT 2018


Author: labath
Date: Wed Mar 21 04:46:37 2018
New Revision: 328090

URL: http://llvm.org/viewvc/llvm-project?rev=328090&view=rev
Log:
[dwarf] Unify unknown dwarf enum formatting code

Summary:
We have had at least three pieces of code (in DWARFAbbreviationDeclaration,
DWARFAcceleratorTable and DWARFDie) that have hand-rolled support for
dumping unknown dwarf enum values. While not terrible, they are a bit
distracting and enable small differences to creep in (Unknown_ffff vs.
Unknown_0xffff). I ended up needing to add a fourth place
(DWARFVerifier), so it seems it would be a good time to centralize.

This patch creates an alternative to the XXXString dumping functions in
the BinaryFormat library, which formats an unknown value as
DW_TYPE_unknown_1234, instead of just an empty string. It is based on
the formatv function, as that allows us to avoid materializing the
string for unknown values (and because this way I don't have to invent a
name for the new functions :P).

In this patch I add formatters for dwarf attributes, forms, tags, and
index attributes as these are the ones in use currently, but adding
other enums is straight-forward.

Reviewers: dblaikie, JDevlieghere, aprantl

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D44570

Modified:
    llvm/trunk/include/llvm/BinaryFormat/Dwarf.h
    llvm/trunk/lib/BinaryFormat/Dwarf.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
    llvm/trunk/unittests/BinaryFormat/DwarfTest.cpp

Modified: llvm/trunk/include/llvm/BinaryFormat/Dwarf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Dwarf.h?rev=328090&r1=328089&r2=328090&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Dwarf.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Dwarf.h Wed Mar 21 04:46:37 2018
@@ -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 @@ enum GDBIndexEntryLinkage { GIEL_EXTERNA
 /// \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,46 @@ private:
   };
 };
 
+template <typename Enum> struct EnumTraits : public std::false_type {};
+
+template <> struct EnumTraits<Attribute> : public std::true_type {
+  static constexpr char Type[] = "AT";
+  static constexpr StringRef (*StringFn)(unsigned) = &AttributeString;
+};
+
+template <> struct EnumTraits<Form> : public std::true_type {
+  static constexpr char Type[] = "FORM";
+  static constexpr StringRef (*StringFn)(unsigned) = &FormEncodingString;
+};
+
+template <> struct EnumTraits<Index> : public std::true_type {
+  static constexpr char Type[] = "IDX";
+  static constexpr StringRef (*StringFn)(unsigned) = &IndexString;
+};
+
+template <> struct EnumTraits<Tag> : 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 <typename Enum>
+struct format_provider<
+    Enum, typename std::enable_if<dwarf::EnumTraits<Enum>::value>::type> {
+  static void format(const Enum &E, raw_ostream &OS, StringRef Style) {
+    StringRef Str = dwarf::EnumTraits<Enum>::StringFn(E);
+    if (Str.empty()) {
+      OS << "DW_" << dwarf::EnumTraits<Enum>::Type << "_unknown_"
+         << llvm::format("%x", E);
+    } else
+      OS << Str;
+  }
+};
 } // End of namespace llvm
 
 #endif

Modified: llvm/trunk/lib/BinaryFormat/Dwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Dwarf.cpp?rev=328090&r1=328089&r2=328090&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Dwarf.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Dwarf.cpp Wed Mar 21 04:46:37 2018
@@ -675,3 +675,8 @@ bool llvm::dwarf::isValidFormForVersion(
   }
   return ExtensionsOk;
 }
+
+const char llvm::dwarf::EnumTraits<Attribute>::Type[];
+const char llvm::dwarf::EnumTraits<Form>::Type[];
+const char llvm::dwarf::EnumTraits<Index>::Type[];
+const char llvm::dwarf::EnumTraits<Tag>::Type[];

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp?rev=328090&r1=328089&r2=328090&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp Wed Mar 21 04:46:37 2018
@@ -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 <cstddef>
 #include <cstdint>
@@ -126,26 +127,11 @@ DWARFAbbreviationDeclaration::extract(Da
 }
 
 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';
-    auto attrString = AttributeString(Spec.Attr);
-    if (!attrString.empty())
-      OS << attrString;
-    else
-      OS << format("DW_AT_Unknown_%x", Spec.Attr);
-    OS << '\t';
-    auto formString = FormEncodingString(Spec.Form);
-    if (!formString.empty())
-      OS << formString;
-    else
-      OS << format("DW_FORM_Unknown_%x", Spec.Form);
+    OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form);
     if (Spec.isImplicitConst())
       OS << '\t' << Spec.getImplicitConstValue();
     OS << '\n';

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp?rev=328090&r1=328089&r2=328090&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp Wed Mar 21 04:46:37 2018
@@ -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 <cstddef>
@@ -24,35 +25,19 @@
 using namespace llvm;
 
 namespace {
-struct DwarfConstant {
-  StringRef (*StringFn)(unsigned);
-  StringRef Type;
+struct Atom {
   unsigned Value;
 };
 
-static raw_ostream &operator<<(raw_ostream &OS, const DwarfConstant &C) {
-  StringRef Str = C.StringFn(C.Value);
+static raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
+  StringRef Str = dwarf::AtomTypeString(A.Value);
   if (!Str.empty())
     return OS << Str;
-  return OS << "DW_" << C.Type << "_Unknown_0x" << format("%x", C.Value);
+  return OS << "DW_ATOM_unknown_" << format("%x", A.Value);
 }
 } // namespace
 
-static DwarfConstant formatTag(unsigned Tag) {
-  return {dwarf::TagString, "TAG", Tag};
-}
-
-static DwarfConstant formatForm(unsigned Form) {
-  return {dwarf::FormEncodingString, "FORM", Form};
-}
-
-static DwarfConstant formatIndex(unsigned Idx) {
-  return {dwarf::IndexString, "IDX", Idx};
-}
-
-static DwarfConstant formatAtom(unsigned Atom) {
-  return {dwarf::AtomTypeString, "ATOM", Atom};
-}
+static Atom formatAtom(unsigned Atom) { return {Atom}; }
 
 DWARFAcceleratorTable::~DWARFAcceleratorTable() = default;
 
@@ -226,7 +211,7 @@ LLVM_DUMP_METHOD void AppleAcceleratorTa
     for (const auto &Atom : HdrData.Atoms) {
       DictScope AtomScope(W, ("Atom " + Twine(i++)).str());
       W.startLine() << "Type: " << formatAtom(Atom.first) << '\n';
-      W.startLine() << "Form: " << formatForm(Atom.second) << '\n';
+      W.startLine() << "Form: " << formatv("{0}", Atom.second) << '\n';
       AtomForms.push_back(DWARFFormValue(Atom.second));
     }
   }
@@ -415,12 +400,10 @@ llvm::Error DWARFDebugNames::Header::ext
 
 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)
-                  << '\n';
-  }
+  for (const auto &Attr : Attributes)
+    W.startLine() << formatv("{0}: {1}\n", Attr.Index, Attr.Form);
 }
 
 static constexpr DWARFDebugNames::AttributeEncoding sentinelAttrEnc() {
@@ -583,11 +566,10 @@ Optional<uint64_t> DWARFDebugNames::Entr
 
 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) << ": ";
+    W.startLine() << formatv("{0}: ", std::get<0>(Tuple).Index);
     std::get<1>(Tuple).dump(W.getOStream());
     W.getOStream() << '\n';
   }

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=328090&r1=328089&r2=328090&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Wed Mar 21 04:46:37 2018
@@ -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"
@@ -188,20 +189,10 @@ static void dumpAttribute(raw_ostream &O
   const char BaseIndent[] = "            ";
   OS << BaseIndent;
   OS.indent(Indent + 2);
-  auto attrString = AttributeString(Attr);
-  if (!attrString.empty())
-    WithColor(OS, HighlightColor::Attribute) << attrString;
-  else
-    WithColor(OS, HighlightColor::Attribute).get()
-        << format("DW_AT_Unknown_%x", Attr);
+  WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr);
 
-  if (DumpOpts.Verbose || DumpOpts.ShowForm) {
-    auto formString = FormEncodingString(Form);
-    if (!formString.empty())
-      OS << " [" << formString << ']';
-    else
-      OS << format(" [DW_FORM_Unknown_%x]", Form);
-  }
+  if (DumpOpts.Verbose || DumpOpts.ShowForm)
+    OS << formatv(" [{0}]", Form);
 
   DWARFUnit *U = Die.getDwarfUnit();
   DWARFFormValue formValue(Form);
@@ -465,13 +456,8 @@ void DWARFDie::dump(raw_ostream &OS, uns
     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() ? '*' : ' ');

Modified: llvm/trunk/unittests/BinaryFormat/DwarfTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/BinaryFormat/DwarfTest.cpp?rev=328090&r1=328089&r2=328090&view=diff
==============================================================================
--- llvm/trunk/unittests/BinaryFormat/DwarfTest.cpp (original)
+++ llvm/trunk/unittests/BinaryFormat/DwarfTest.cpp Wed Mar 21 04:46:37 2018
@@ -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,14 @@ TEST(DwarfTest, FixedFormSizes) {
   EXPECT_EQ(*RefSize, 8);
 }
 
+TEST(DwarfTest, format_provider) {
+  EXPECT_EQ("DW_AT_name", formatv("{0}", DW_AT_name).str());
+  EXPECT_EQ("DW_AT_unknown_3fff", formatv("{0}", DW_AT_hi_user).str());
+  EXPECT_EQ("DW_FORM_addr", formatv("{0}", DW_FORM_addr).str());
+  EXPECT_EQ("DW_FORM_unknown_1f00", formatv("{0}", DW_FORM_lo_user).str());
+  EXPECT_EQ("DW_IDX_compile_unit", formatv("{0}", DW_IDX_compile_unit).str());
+  EXPECT_EQ("DW_IDX_unknown_3fff", formatv("{0}", DW_IDX_hi_user).str());
+  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




More information about the llvm-commits mailing list