[llvm] r297067 - [ObjectYAML] NFC. Refactor DWARFYAML CompileUnit dump code

Chris Bieneman via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 6 12:52:12 PST 2017


Author: cbieneman
Date: Mon Mar  6 14:52:12 2017
New Revision: 297067

URL: http://llvm.org/viewvc/llvm-project?rev=297067&view=rev
Log:
[ObjectYAML] NFC. Refactor DWARFYAML CompileUnit dump code

Summary: This patch refactors the DWARFYAML code for dumping compile units to use a visitor pattern. Using this design will, in the future, enable the DWARF YAML code to perform analysis and mutations of the DWARF DIEs. An example of such mutations would be calculating the length of a compile unit and updating the CU's Length field before writing the DIE. This support will make it easier to craft or modify DWARF tests by hand.

Reviewers: lhames

Subscribers: mgorny, fhahn, jgosnell, aprantl, llvm-commits

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

Added:
    llvm/trunk/lib/ObjectYAML/DWARFVisitor.cpp
    llvm/trunk/lib/ObjectYAML/DWARFVisitor.h
Modified:
    llvm/trunk/lib/ObjectYAML/CMakeLists.txt
    llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp

Modified: llvm/trunk/lib/ObjectYAML/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CMakeLists.txt?rev=297067&r1=297066&r2=297067&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CMakeLists.txt (original)
+++ llvm/trunk/lib/ObjectYAML/CMakeLists.txt Mon Mar  6 14:52:12 2017
@@ -1,6 +1,7 @@
 add_llvm_library(LLVMObjectYAML
   COFFYAML.cpp
   DWARFEmitter.cpp
+  DWARFVisitor.cpp
   DWARFYAML.cpp
   ELFYAML.cpp
   MachOYAML.cpp

Modified: llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp?rev=297067&r1=297066&r2=297067&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/DWARFEmitter.cpp Mon Mar  6 14:52:12 2017
@@ -19,6 +19,8 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/SwapByteOrder.h"
 
+#include "DWARFVisitor.h"
+
 #include <algorithm>
 
 using namespace llvm;
@@ -117,130 +119,65 @@ void DWARFYAML::EmitPubSection(raw_ostre
   }
 }
 
-void DWARFYAML::EmitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
+/// \brief An extension of the DWARFYAML::ConstVisitor which writes compile
+/// units and DIEs to a stream.
+class DumpVisitor : public DWARFYAML::ConstVisitor {
+  raw_ostream &OS;
+
+protected:
+  virtual void onStartCompileUnit(const DWARFYAML::Unit &CU) {
+    writeInitialLength(CU.Length, OS, DebugInfo.IsLittleEndian);
+    writeInteger((uint16_t)CU.Version, OS, DebugInfo.IsLittleEndian);
+    writeInteger((uint32_t)CU.AbbrOffset, OS, DebugInfo.IsLittleEndian);
+    writeInteger((uint8_t)CU.AddrSize, OS, DebugInfo.IsLittleEndian);
+  }
 
-  for (auto CU : DI.CompileUnits) {
-    writeInitialLength(CU.Length, OS, DI.IsLittleEndian);
-    writeInteger((uint16_t)CU.Version, OS, DI.IsLittleEndian);
-    writeInteger((uint32_t)CU.AbbrOffset, OS, DI.IsLittleEndian);
-    writeInteger((uint8_t)CU.AddrSize, OS, DI.IsLittleEndian);
-
-    auto FirstAbbrevCode = CU.Entries[0].AbbrCode;
-
-    for (auto Entry : CU.Entries) {
-      encodeULEB128(Entry.AbbrCode, OS);
-      if (Entry.AbbrCode == 0u)
-        continue;
-      bool Indirect = false;
-      assert(Entry.AbbrCode - FirstAbbrevCode < DI.AbbrevDecls.size() &&
-             "Out of range AbbCode");
-      auto &Abbrev = DI.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
-
-      auto FormVal = Entry.Values.begin();
-      auto AbbrForm = Abbrev.Attributes.begin();
-      for (;
-           FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
-           ++FormVal, ++AbbrForm) {
-        dwarf::Form Form = AbbrForm->Form;
-        do {
-          Indirect = false;
-          switch (Form) {
-          case dwarf::DW_FORM_addr:
-            writeVariableSizedInteger(FormVal->Value, CU.AddrSize, OS,
-                                      DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_ref_addr: {
-            // TODO: Handle DWARF32/DWARF64 after Line Table data is done
-            auto writeSize = CU.Version == 2 ? CU.AddrSize : 4;
-            writeVariableSizedInteger(FormVal->Value, writeSize, OS,
-                                      DI.IsLittleEndian);
-            break;
-          }
-          case dwarf::DW_FORM_exprloc:
-          case dwarf::DW_FORM_block:
-            encodeULEB128(FormVal->BlockData.size(), OS);
-            OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
-                     FormVal->BlockData.size());
-            break;
-          case dwarf::DW_FORM_block1: {
-            auto writeSize = FormVal->BlockData.size();
-            writeInteger((uint8_t)writeSize, OS, DI.IsLittleEndian);
-            OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
-                     FormVal->BlockData.size());
-            break;
-          }
-          case dwarf::DW_FORM_block2: {
-            auto writeSize = FormVal->BlockData.size();
-            writeInteger((uint16_t)writeSize, OS, DI.IsLittleEndian);
-            OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
-                     FormVal->BlockData.size());
-            break;
-          }
-          case dwarf::DW_FORM_block4: {
-            auto writeSize = FormVal->BlockData.size();
-            writeInteger((uint32_t)writeSize, OS, DI.IsLittleEndian);
-            OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
-                     FormVal->BlockData.size());
-            break;
-          }
-          case dwarf::DW_FORM_data1:
-          case dwarf::DW_FORM_ref1:
-          case dwarf::DW_FORM_flag:
-            writeInteger((uint8_t)FormVal->Value, OS, DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_data2:
-          case dwarf::DW_FORM_ref2:
-            writeInteger((uint16_t)FormVal->Value, OS, DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_data4:
-          case dwarf::DW_FORM_ref4:
-            writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_data8:
-          case dwarf::DW_FORM_ref8:
-            writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_sdata:
-            encodeSLEB128(FormVal->Value, OS);
-            break;
-          case dwarf::DW_FORM_udata:
-          case dwarf::DW_FORM_ref_udata:
-            encodeULEB128(FormVal->Value, OS);
-            break;
-          case dwarf::DW_FORM_string:
-            OS.write(FormVal->CStr.data(), FormVal->CStr.size());
-            OS.write('\0');
-            break;
-          case dwarf::DW_FORM_indirect:
-            encodeULEB128(FormVal->Value, OS);
-            Indirect = true;
-            Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
-            ++FormVal;
-            break;
-          case dwarf::DW_FORM_strp:
-          case dwarf::DW_FORM_sec_offset:
-          case dwarf::DW_FORM_GNU_ref_alt:
-          case dwarf::DW_FORM_GNU_strp_alt:
-          case dwarf::DW_FORM_line_strp:
-          case dwarf::DW_FORM_strp_sup:
-          case dwarf::DW_FORM_ref_sup:
-            // TODO: Handle DWARF32/64
-            writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_ref_sig8:
-            writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
-            break;
-          case dwarf::DW_FORM_GNU_addr_index:
-          case dwarf::DW_FORM_GNU_str_index:
-            encodeULEB128(FormVal->Value, OS);
-            break;
-          default:
-            break;
-          }
-        } while (Indirect);
-      }
-    }
+  virtual void onStartDIE(const DWARFYAML::Unit &CU,
+                          const DWARFYAML::Entry &DIE) {
+    encodeULEB128(DIE.AbbrCode, OS);
+  }
+
+  virtual void onValue(const uint8_t U) {
+    writeInteger(U, OS, DebugInfo.IsLittleEndian);
+  }
+
+  virtual void onValue(const uint16_t U) {
+    writeInteger(U, OS, DebugInfo.IsLittleEndian);
+  }
+  virtual void onValue(const uint32_t U) {
+    writeInteger(U, OS, DebugInfo.IsLittleEndian);
+  }
+  virtual void onValue(const uint64_t U, const bool LEB = false) {
+    if (LEB)
+      encodeULEB128(U, OS);
+    else
+      writeInteger(U, OS, DebugInfo.IsLittleEndian);
   }
+
+  virtual void onValue(const int64_t S, const bool LEB = false) {
+    if (LEB)
+      encodeSLEB128(S, OS);
+    else
+      writeInteger(S, OS, DebugInfo.IsLittleEndian);
+  }
+
+  virtual void onValue(const StringRef String) {
+    OS.write(String.data(), String.size());
+    OS.write('\0');
+  }
+
+  virtual void onValue(const MemoryBufferRef MBR) {
+    OS.write(MBR.getBufferStart(), MBR.getBufferSize());
+  }
+
+public:
+  DumpVisitor(const DWARFYAML::Data &DI, raw_ostream &Out)
+      : DWARFYAML::ConstVisitor(DI), OS(Out) {}
+};
+
+void DWARFYAML::EmitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
+  DumpVisitor Visitor(DI, OS);
+  Visitor.traverseDebugInfo();
 }
 
 static void EmitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {

Added: llvm/trunk/lib/ObjectYAML/DWARFVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/DWARFVisitor.cpp?rev=297067&view=auto
==============================================================================
--- llvm/trunk/lib/ObjectYAML/DWARFVisitor.cpp (added)
+++ llvm/trunk/lib/ObjectYAML/DWARFVisitor.cpp Mon Mar  6 14:52:12 2017
@@ -0,0 +1,167 @@
+//===--- DWARFVisitor.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFVisitor.h"
+#include "llvm/ObjectYAML/DWARFYAML.h"
+
+using namespace llvm;
+
+template <typename T>
+void DWARFYAML::VisitorImpl<T>::onVariableSizeValue(uint64_t U, unsigned Size) {
+  switch (Size) {
+  case 8:
+    onValue((uint64_t)U);
+    break;
+  case 4:
+    onValue((uint32_t)U);
+    break;
+  case 2:
+    onValue((uint16_t)U);
+    break;
+  case 1:
+    onValue((uint8_t)U);
+    break;
+  default:
+    llvm_unreachable("Invalid integer write size.");
+  }
+}
+
+unsigned getRefSize(const DWARFYAML::Unit &Unit) {
+  if (Unit.Version == 2)
+    return Unit.AddrSize;
+  return Unit.Length.isDWARF64() ? 8 : 4;
+}
+
+template <typename T> void DWARFYAML::VisitorImpl<T>::traverseDebugInfo() {
+  for (auto &Unit : DebugInfo.CompileUnits) {
+    onStartCompileUnit(Unit);
+    auto FirstAbbrevCode = Unit.Entries[0].AbbrCode;
+
+    for (auto &Entry : Unit.Entries) {
+      onStartDIE(Unit, Entry);
+      if (Entry.AbbrCode == 0u)
+        continue;
+      auto &Abbrev = DebugInfo.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
+      auto FormVal = Entry.Values.begin();
+      auto AbbrForm = Abbrev.Attributes.begin();
+      for (;
+           FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
+           ++FormVal, ++AbbrForm) {
+        onForm(*AbbrForm, *FormVal);
+        dwarf::Form Form = AbbrForm->Form;
+        bool Indirect;
+        do {
+          Indirect = false;
+          switch (Form) {
+          case dwarf::DW_FORM_addr:
+            onVariableSizeValue(FormVal->Value, Unit.AddrSize);
+            break;
+          case dwarf::DW_FORM_ref_addr:
+            onVariableSizeValue(FormVal->Value, getRefSize(Unit));
+            break;
+          case dwarf::DW_FORM_exprloc:
+          case dwarf::DW_FORM_block:
+            onValue((uint64_t)FormVal->BlockData.size(), true);
+            onValue(
+                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+                                          FormVal->BlockData.size()),
+                                ""));
+            break;
+          case dwarf::DW_FORM_block1: {
+            auto writeSize = FormVal->BlockData.size();
+            onValue((uint8_t)writeSize);
+            onValue(
+                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+                                          FormVal->BlockData.size()),
+                                ""));
+            break;
+          }
+          case dwarf::DW_FORM_block2: {
+            auto writeSize = FormVal->BlockData.size();
+            onValue((uint16_t)writeSize);
+            onValue(
+                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+                                          FormVal->BlockData.size()),
+                                ""));
+            break;
+          }
+          case dwarf::DW_FORM_block4: {
+            auto writeSize = FormVal->BlockData.size();
+            onValue((uint32_t)writeSize);
+            onValue(
+                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
+                                          FormVal->BlockData.size()),
+                                ""));
+            break;
+          }
+          case dwarf::DW_FORM_data1:
+          case dwarf::DW_FORM_ref1:
+          case dwarf::DW_FORM_flag:
+            onValue((uint8_t)FormVal->Value);
+            break;
+          case dwarf::DW_FORM_data2:
+          case dwarf::DW_FORM_ref2:
+            onValue((uint16_t)FormVal->Value);
+            break;
+          case dwarf::DW_FORM_data4:
+          case dwarf::DW_FORM_ref4:
+            onValue((uint32_t)FormVal->Value);
+            break;
+          case dwarf::DW_FORM_data8:
+          case dwarf::DW_FORM_ref8:
+            onValue((uint64_t)FormVal->Value);
+            break;
+          case dwarf::DW_FORM_sdata:
+            onValue((int64_t)FormVal->Value, true);
+            break;
+          case dwarf::DW_FORM_udata:
+          case dwarf::DW_FORM_ref_udata:
+            onValue((uint64_t)FormVal->Value, true);
+            break;
+          case dwarf::DW_FORM_string:
+            onValue(FormVal->CStr);
+            break;
+          case dwarf::DW_FORM_indirect:
+            onValue((uint64_t)FormVal->Value, true);
+            Indirect = true;
+            Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
+            ++FormVal;
+            break;
+          case dwarf::DW_FORM_strp:
+          case dwarf::DW_FORM_sec_offset:
+          case dwarf::DW_FORM_GNU_ref_alt:
+          case dwarf::DW_FORM_GNU_strp_alt:
+          case dwarf::DW_FORM_line_strp:
+          case dwarf::DW_FORM_strp_sup:
+          case dwarf::DW_FORM_ref_sup:
+            onVariableSizeValue(FormVal->Value, getRefSize(Unit));
+            break;
+          case dwarf::DW_FORM_ref_sig8:
+            onValue((uint64_t)FormVal->Value);
+            break;
+          case dwarf::DW_FORM_GNU_addr_index:
+          case dwarf::DW_FORM_GNU_str_index:
+            onValue((uint64_t)FormVal->Value, true);
+            break;
+          default:
+            break;
+          }
+        } while (Indirect);
+      }
+      onEndDIE(Unit, Entry);
+    }
+    onEndCompileUnit(Unit);
+  }
+}
+
+// Explicitly instantiate the two template expansions.
+template class DWARFYAML::VisitorImpl<DWARFYAML::Data>;
+template class DWARFYAML::VisitorImpl<const DWARFYAML::Data>;

Added: llvm/trunk/lib/ObjectYAML/DWARFVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/DWARFVisitor.h?rev=297067&view=auto
==============================================================================
--- llvm/trunk/lib/ObjectYAML/DWARFVisitor.h (added)
+++ llvm/trunk/lib/ObjectYAML/DWARFVisitor.h Mon Mar  6 14:52:12 2017
@@ -0,0 +1,97 @@
+//===--- DWARFVisitor.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_DWARFVISITOR_H
+#define LLVM_OBJECTYAML_DWARFVISITOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace llvm {
+
+namespace DWARFYAML {
+
+struct Data;
+struct Unit;
+struct Entry;
+struct FormValue;
+struct AttributeAbbrev;
+
+/// \brief A class to visits DWARFYAML Compile Units and DIEs in preorder.
+///
+/// Extensions of this class can either maintain const or non-const references
+/// to the DWARFYAML::Data object.
+template <typename T> class VisitorImpl {
+protected:
+  T &DebugInfo;
+
+  /// Visitor Functions
+  /// @{
+  virtual void onStartCompileUnit(Unit &CU) {}
+  virtual void onEndCompileUnit(Unit &CU) {}
+  virtual void onStartDIE(Unit &CU, Entry &DIE) {}
+  virtual void onEndDIE(Unit &CU, Entry &DIE) {}
+  virtual void onForm(AttributeAbbrev &AttAbbrev, FormValue &Value) {}
+  /// @}
+
+  /// Const Visitor Functions
+  /// @{
+  virtual void onStartCompileUnit(const Unit &CU) {}
+  virtual void onEndCompileUnit(const Unit &CU) {}
+  virtual void onStartDIE(const Unit &CU, const Entry &DIE) {}
+  virtual void onEndDIE(const Unit &CU, const Entry &DIE) {}
+  virtual void onForm(const AttributeAbbrev &AttAbbrev,
+                      const FormValue &Value) {}
+  /// @}
+
+  /// Value visitors
+  /// @{
+  virtual void onValue(const uint8_t U) {}
+  virtual void onValue(const uint16_t U) {}
+  virtual void onValue(const uint32_t U) {}
+  virtual void onValue(const uint64_t U, const bool LEB = false) {}
+  virtual void onValue(const int64_t S, const bool LEB = false) {}
+  virtual void onValue(const StringRef String) {}
+  virtual void onValue(const MemoryBufferRef MBR) {}
+  /// @}
+
+public:
+  VisitorImpl(T &DI) : DebugInfo(DI) {}
+
+  virtual ~VisitorImpl() {}
+
+  void traverseDebugInfo();
+
+private:
+  void onVariableSizeValue(uint64_t U, unsigned Size);
+};
+
+// Making the visior instantiations extern and explicit in the cpp file. This
+// prevents them from being instantiated in every compile unit that uses the
+// visitors.
+extern template class VisitorImpl<DWARFYAML::Data>;
+extern template class VisitorImpl<const DWARFYAML::Data>;
+
+class Visitor : public VisitorImpl<Data> {
+public:
+  Visitor(Data &DI) : VisitorImpl<Data>(DI) {}
+};
+
+class ConstVisitor : public VisitorImpl<const Data> {
+public:
+  ConstVisitor(const Data &DI) : VisitorImpl<const Data>(DI) {}
+};
+
+} // namespace DWARFYAML
+} // namespace llvm
+
+#endif




More information about the llvm-commits mailing list