[llvm] r283609 - Refactor Symbol visitor code.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 7 14:34:47 PDT 2016


Author: zturner
Date: Fri Oct  7 16:34:46 2016
New Revision: 283609

URL: http://llvm.org/viewvc/llvm-project?rev=283609&view=rev
Log:
Refactor Symbol visitor code.

Type visitor code had already been refactored previously to
decouple the visitor and the visitor callback interface.  This
was necessary for having the flexibility to visit in different
ways (for example, dumping to yaml, reading from yaml, dumping
to ScopedPrinter, etc).

This patch merely implements the same visitation pattern for
symbol records that has already been implemented for type records.

Added:
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h
    llvm/trunk/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDumper.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
    llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/CodeView/SymbolDumper.cpp
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h Fri Oct  7 16:34:46 2016
@@ -18,85 +18,17 @@
 
 namespace llvm {
 namespace codeview {
+class SymbolVisitorCallbacks;
 
-template <typename Derived> class CVSymbolVisitor {
+class CVSymbolVisitor {
 public:
-  CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {}
+  CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks);
 
-  bool hadError() const { return HadError; }
-
-  template <typename T>
-  bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
-    if (Data.size() < sizeof(*Res)) {
-      HadError = true;
-      return false;
-    }
-    Res = reinterpret_cast<const T *>(Data.data());
-    Data = Data.drop_front(sizeof(*Res));
-    return true;
-  }
-
-/// Actions to take on known symbols. By default, they do nothing. Visit methods
-/// for member records take the FieldData by non-const reference and are
-/// expected to consume the trailing bytes used by the field.
-/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
-/// need to.
-#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
-  void visit##Name(SymbolRecordKind Kind, Name &Record) {}
-#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "CVSymbolTypes.def"
-
-  void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
-    ArrayRef<uint8_t> Data = Record.content();
-    auto *DerivedThis = static_cast<Derived *>(this);
-    DerivedThis->visitSymbolBegin(Record.Type, Data);
-    uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
-    switch (Record.Type) {
-    default:
-      DerivedThis->visitUnknownSymbol(Record.Type, Data);
-      break;
-#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
-  case EnumName: {                                                             \
-    SymbolRecordKind RK = static_cast<SymbolRecordKind>(EnumName);             \
-    auto ExpectedResult = Name::deserialize(RK, RecordOffset, Data);           \
-    if (!ExpectedResult) {                                                     \
-      consumeError(ExpectedResult.takeError());                                \
-      return parseError();                                                     \
-    }                                                                          \
-    DerivedThis->visit##Name(Record.Type, *ExpectedResult);                    \
-    break;                                                                     \
-  }
-#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
-  SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
-#include "CVSymbolTypes.def"
-    }
-    DerivedThis->visitSymbolEnd(Record.Type, Record.content());
-  }
-
-  /// Visits the symbol records in Data. Sets the error flag on parse failures.
-  void visitSymbolStream(const CVSymbolArray &Symbols) {
-    for (const auto &I : Symbols) {
-      visitSymbolRecord(I);
-      if (hadError())
-        break;
-    }
-  }
-
-  /// Action to take on unknown symbols. By default, they are ignored.
-  void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) {}
-
-  /// Paired begin/end actions for all symbols. Receives all record data,
-  /// including the fixed-length record prefix.
-  void visitSymbolBegin(SymbolKind Leaf, ArrayRef<uint8_t> RecordData) {}
-  void visitSymbolEnd(SymbolKind Leaf, ArrayRef<uint8_t> OriginalSymData) {}
-
-  /// Helper for returning from a void function when the stream is corrupted.
-  void parseError() { HadError = true; }
+  Error visitSymbolRecord(CVSymbol &Record);
+  Error visitSymbolStream(const CVSymbolArray &Symbols);
 
 private:
-  SymbolVisitorDelegate *Delegate;
-  /// Whether a symbol stream parsing error was encountered.
-  bool HadError = false;
+  SymbolVisitorCallbacks &Callbacks;
 };
 
 } // end namespace codeview

Added: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h?rev=283609&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h Fri Oct  7 16:34:46 2016
@@ -0,0 +1,60 @@
+//===- SymbolDeserializer.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_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class SymbolVisitorDelegate;
+class SymbolDeserializer : public SymbolVisitorCallbacks {
+public:
+  explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate)
+      : Delegate(Delegate) {}
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override {               \
+    return defaultVisitKnownRecord(CVR, Record);                               \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "CVSymbolTypes.def"
+
+protected:
+  template <typename T>
+  Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind,
+                          T &Record) const {
+    uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
+    SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
+    auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data);
+    if (!ExpectedRecord)
+      return ExpectedRecord.takeError();
+    Record = std::move(*ExpectedRecord);
+    return Error::success();
+  }
+
+private:
+  template <typename T>
+  Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
+    ArrayRef<uint8_t> RD = CVR.content();
+    if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+      return EC;
+    return Error::success();
+  }
+
+  SymbolVisitorDelegate *Delegate;
+};
+}
+}
+
+#endif

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDumper.h?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDumper.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolDumper.h Fri Oct  7 16:34:46 2016
@@ -35,11 +35,11 @@ public:
   /// and true otherwise.  This should be called in order, since the dumper
   /// maintains state about previous records which are necessary for cross
   /// type references.
-  bool dump(const CVRecord<SymbolKind> &Record);
+  Error dump(CVRecord<SymbolKind> &Record);
 
   /// Dumps the type records in Data. Returns false if there was a type stream
   /// parse error, and true otherwise.
-  bool dump(const CVSymbolArray &Symbols);
+  Error dump(const CVSymbolArray &Symbols);
 
 private:
   ScopedPrinter &W;

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h Fri Oct  7 16:34:46 2016
@@ -56,6 +56,7 @@ public:
                    // Name: The null-terminated name follows.
   };
 
+  explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
           StringRef Name)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@@ -95,6 +96,7 @@ public:
                  // Variant portion of thunk
   };
 
+  explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
              StringRef Name, ArrayRef<uint8_t> VariantData)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name),
@@ -130,6 +132,7 @@ public:
     ulittle16_t TargetSection;
   };
 
+  explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
 
@@ -160,6 +163,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
              StringRef Name)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@@ -192,6 +196,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
                StringRef Name)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@@ -215,6 +220,7 @@ public:
 
 class ScopeEndSym : public SymbolRecord {
 public:
+  explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
 
@@ -232,6 +238,7 @@ public:
     ulittle32_t Count;
   };
 
+  explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
             ArrayRef<TypeIndex> Indices)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
@@ -441,6 +448,7 @@ public:
     // BinaryAnnotations
   };
 
+  explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
                 ArrayRef<uint8_t> Annotations)
       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
@@ -478,6 +486,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -506,6 +515,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -535,6 +545,7 @@ public:
                            // Name:  The null-terminated name follows.
   };
 
+  explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -563,6 +574,7 @@ public:
                        // Name: The null-terminated name follows.
   };
 
+  explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -604,6 +616,7 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeSym(uint32_t RecordOffset, const Hdr *H,
               ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
@@ -637,6 +650,7 @@ public:
     LocalVariableAddrRange Range;
     // LocalVariableAddrGap Gaps[];
   };
+  explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
                       ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
@@ -671,6 +685,7 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
                       ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
@@ -715,6 +730,8 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
+      : SymbolRecord(Kind) {}
   DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
                               ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
@@ -759,6 +776,8 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
+      : SymbolRecord(Kind) {}
   DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
                              ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
@@ -794,6 +813,7 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
                          ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
@@ -848,6 +868,8 @@ public:
     little32_t Offset; // Offset from the frame pointer register
   };
 
+  explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
+      : SymbolRecord(Kind) {}
   DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -877,6 +899,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -910,6 +933,7 @@ public:
                    // Name: The null-terminated name follows.
   };
 
+  explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -941,6 +965,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -968,6 +993,7 @@ public:
     // Sequence of zero terminated strings.
   };
 
+  explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   EnvBlockSym(uint32_t RecordOffset, const Hdr *H,
               const std::vector<StringRef> &Fields)
       : SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset),
@@ -997,6 +1023,7 @@ public:
                        // Name: The null-terminated name follows.
   };
 
+  explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -1026,6 +1053,7 @@ public:
                                    // Name: The null-terminated name follows.
   };
 
+  explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::FileStaticSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@@ -1062,6 +1090,7 @@ public:
     // Optional block of zero terminated strings terminated with a double zero.
   };
 
+  explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
       : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
         Header(*H), Version(Version) {}
@@ -1099,6 +1128,7 @@ public:
     // VersionString: The null-terminated version string follows.
   };
 
+  explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
       : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
         Header(*H), Version(Version) {}
@@ -1131,6 +1161,7 @@ public:
     ulittle32_t Flags;
   };
 
+  explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   FrameProcSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::FrameProcSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1158,6 +1189,7 @@ public:
     TypeIndex Type;
   };
 
+  explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1189,6 +1221,7 @@ public:
     TypeIndex Type;
   };
 
+  explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1220,6 +1253,7 @@ public:
     uint8_t Flags;
   };
 
+  explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::FrameCookieSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1249,6 +1283,7 @@ public:
                     // Name: The null-terminated name follows.
   };
 
+  explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -1275,6 +1310,7 @@ public:
     ulittle32_t BuildId;
   };
 
+  explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1301,6 +1337,7 @@ public:
                        // Name: The null-terminated name follows.
   };
 
+  explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@@ -1330,6 +1367,7 @@ public:
                           // Name: The null-terminated name follows.
   };
 
+  explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@@ -1358,6 +1396,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
               StringRef Name)
       : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
@@ -1390,6 +1429,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -1423,6 +1463,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}

Added: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h?rev=283609&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h Fri Oct  7 16:34:46 2016
@@ -0,0 +1,69 @@
+//===- SymbolVisitorCallbackPipeline.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_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class SymbolVisitorCallbackPipeline : public SymbolVisitorCallbacks {
+public:
+  SymbolVisitorCallbackPipeline() {}
+
+  virtual Error visitUnknownSymbol(CVSymbol &Record) override {
+    for (auto Visitor : Pipeline) {
+      if (auto EC = Visitor->visitUnknownSymbol(Record))
+        return EC;
+    }
+    return Error::success();
+  }
+
+  virtual Error visitSymbolBegin(CVSymbol &Record) override {
+    for (auto Visitor : Pipeline) {
+      if (auto EC = Visitor->visitSymbolBegin(Record))
+        return EC;
+    }
+    return Error::success();
+  }
+  virtual Error visitSymbolEnd(CVSymbol &Record) override {
+    for (auto Visitor : Pipeline) {
+      if (auto EC = Visitor->visitSymbolEnd(Record))
+        return EC;
+    }
+    return Error::success();
+  }
+
+  void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks) {
+    Pipeline.push_back(&Callbacks);
+  }
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override {               \
+    for (auto Visitor : Pipeline) {                                            \
+      if (auto EC = Visitor->visitKnownRecord(CVR, Record))                    \
+        return EC;                                                             \
+    }                                                                          \
+    return Error::success();                                                   \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+
+private:
+  std::vector<SymbolVisitorCallbacks *> Pipeline;
+};
+}
+}
+
+#endif

Added: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h?rev=283609&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h Fri Oct  7 16:34:46 2016
@@ -0,0 +1,49 @@
+//===- SymbolVisitorCallbacks.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_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class SymbolVisitorCallbacks {
+  friend class CVSymbolVisitor;
+
+public:
+  virtual ~SymbolVisitorCallbacks() {}
+
+  /// Action to take on unknown symbols. By default, they are ignored.
+  virtual Error visitUnknownSymbol(CVSymbol &Record) {
+    return Error::success();
+  }
+
+  /// Paired begin/end actions for all symbols. Receives all record data,
+  /// including the fixed-length record prefix.  visitSymbolBegin() should
+  /// return
+  /// the type of the Symbol, or an error if it cannot be determined.
+  virtual Error visitSymbolBegin(CVSymbol &Record) { return Error::success(); }
+  virtual Error visitSymbolEnd(CVSymbol &Record) { return Error::success(); }
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) {                \
+    return Error::success();                                                   \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "CVSymbolTypes.def"
+};
+}
+}
+
+#endif

Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Fri Oct  7 16:34:46 2016
@@ -1,5 +1,6 @@
 add_llvm_library(LLVMDebugInfoCodeView
   CodeViewError.cpp
+  CVSymbolVisitor.cpp
   CVTypeVisitor.cpp
   EnumTables.cpp
   FieldListRecordBuilder.cpp

Added: llvm/trunk/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp?rev=283609&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp (added)
+++ llvm/trunk/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp Fri Oct  7 16:34:46 2016
@@ -0,0 +1,73 @@
+//===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename T>
+static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+  if (Data.size() < sizeof(*Res))
+    return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+  Res = reinterpret_cast<const T *>(Data.data());
+  Data = Data.drop_front(sizeof(*Res));
+  return Error::success();
+}
+
+CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
+    : Callbacks(Callbacks) {}
+
+template <typename T>
+static Error visitKnownRecord(CVSymbol &Record,
+                              SymbolVisitorCallbacks &Callbacks) {
+  SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+    return EC;
+  return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
+  if (auto EC = Callbacks.visitSymbolBegin(Record))
+    return EC;
+
+  switch (Record.Type) {
+  default:
+    if (auto EC = Callbacks.visitUnknownSymbol(Record))
+      return EC;
+    break;
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    if (auto EC = visitKnownRecord<Name>(Record, Callbacks))                   \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+  }
+
+  if (auto EC = Callbacks.visitSymbolEnd(Record))
+    return EC;
+
+  return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
+  for (auto I : Symbols) {
+    if (auto EC = visitSymbolRecord(I))
+      return EC;
+  }
+  return Error::success();
+}

Modified: llvm/trunk/lib/DebugInfo/CodeView/SymbolDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/SymbolDumper.cpp?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/SymbolDumper.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/SymbolDumper.cpp Fri Oct  7 16:34:46 2016
@@ -12,10 +12,14 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 #include <system_error>
@@ -26,22 +30,22 @@ using namespace llvm::codeview;
 namespace {
 /// Use this private dumper implementation to keep implementation details about
 /// the visitor out of SymbolDumper.h.
-class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
+class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
 public:
   CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
                      ScopedPrinter &W, bool PrintRecordBytes)
-      : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
-        W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
+      : CVTD(CVTD), ObjDelegate(ObjDelegate), W(W),
+        PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
 
 /// CVSymbolVisitor overrides.
 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
-  void visit##Name(SymbolKind Kind, Name &Record);
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
 
-  void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
-  void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
-  void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
+  Error visitSymbolBegin(CVSymbol &Record) override;
+  Error visitSymbolEnd(CVSymbol &Record) override;
+  Error visitUnknownSymbol(CVSymbol &Record) override;
 
 private:
   void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
@@ -76,16 +80,17 @@ void CVSymbolDumperImpl::printLocalVaria
   }
 }
 
-void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
-                                          ArrayRef<uint8_t> Data) {}
+Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
+  return Error::success();
+}
 
-void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
-                                        ArrayRef<uint8_t> OriginalSymData) {
+Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
   if (PrintRecordBytes && ObjDelegate)
-    ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
+    ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
   DictScope S(W, "BlockStart");
 
   StringRef LinkageName;
@@ -99,9 +104,10 @@ void CVSymbolDumperImpl::visitBlockSym(S
   W.printHex("Segment", Block.Header.Segment);
   W.printString("BlockName", Block.Name);
   W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
   DictScope S(W, "Thunk32");
   W.printNumber("Parent", Thunk.Header.Parent);
   W.printNumber("End", Thunk.Header.End);
@@ -110,10 +116,11 @@ void CVSymbolDumperImpl::visitThunk32Sym
   W.printNumber("Seg", Thunk.Header.Seg);
   W.printNumber("Len", Thunk.Header.Len);
   W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
-                                            TrampolineSym &Tramp) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           TrampolineSym &Tramp) {
   DictScope S(W, "Trampoline");
   W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
   W.printNumber("Size", Tramp.Header.Size);
@@ -121,9 +128,10 @@ void CVSymbolDumperImpl::visitTrampoline
   W.printNumber("TargetOff", Tramp.Header.TargetOff);
   W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
   W.printNumber("TargetSection", Tramp.Header.TargetSection);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
   DictScope S(W, "Section");
   W.printNumber("SectionNumber", Section.Header.SectionNumber);
   W.printNumber("Alignment", Section.Header.Alignment);
@@ -135,9 +143,10 @@ void CVSymbolDumperImpl::visitSectionSym
                COFF::SectionCharacteristics(0x00F00000));
 
   W.printString("Name", Section.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                            CoffGroupSym &CoffGroup) {
   DictScope S(W, "COFF Group");
   W.printNumber("Size", CoffGroup.Header.Size);
@@ -147,26 +156,29 @@ void CVSymbolDumperImpl::visitCoffGroupS
   W.printNumber("Offset", CoffGroup.Header.Offset);
   W.printNumber("Segment", CoffGroup.Header.Segment);
   W.printString("Name", CoffGroup.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
-                                            BPRelativeSym &BPRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           BPRelativeSym &BPRel) {
   DictScope S(W, "BPRelativeSym");
 
   W.printNumber("Offset", BPRel.Header.Offset);
   CVTD.printTypeIndex("Type", BPRel.Header.Type);
   W.printString("VarName", BPRel.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                            BuildInfoSym &BuildInfo) {
   DictScope S(W, "BuildInfo");
 
   W.printNumber("BuildId", BuildInfo.Header.BuildId);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
-                                              CallSiteInfoSym &CallSiteInfo) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           CallSiteInfoSym &CallSiteInfo) {
   DictScope S(W, "CallSiteInfo");
 
   StringRef LinkageName;
@@ -180,10 +192,11 @@ void CVSymbolDumperImpl::visitCallSiteIn
   CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
-                                          EnvBlockSym &EnvBlock) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           EnvBlockSym &EnvBlock) {
   DictScope S(W, "EnvBlock");
 
   W.printNumber("Reserved", EnvBlock.Header.Reserved);
@@ -191,26 +204,29 @@ void CVSymbolDumperImpl::visitEnvBlockSy
   for (auto Entry : EnvBlock.Fields) {
     W.printString(Entry);
   }
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
-                                            FileStaticSym &FileStatic) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FileStaticSym &FileStatic) {
   DictScope S(W, "FileStatic");
   W.printNumber("Index", FileStatic.Header.Index);
   W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
   W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
   W.printString("Name", FileStatic.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
   DictScope S(W, "Export");
   W.printNumber("Ordinal", Export.Header.Ordinal);
   W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
   W.printString("Name", Export.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
-                                          Compile2Sym &Compile2) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           Compile2Sym &Compile2) {
   DictScope S(W, "CompilerFlags2");
 
   W.printEnum("Language", Compile2.Header.getLanguage(),
@@ -235,10 +251,11 @@ void CVSymbolDumperImpl::visitCompile2Sy
   W.printString("FrontendVersion", FrontendVersion);
   W.printString("BackendVersion", BackendVersion);
   W.printString("VersionName", Compile2.Version);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
-                                          Compile3Sym &Compile3) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           Compile3Sym &Compile3) {
   DictScope S(W, "CompilerFlags3");
 
   W.printEnum("Language", Compile3.Header.getLanguage(),
@@ -265,21 +282,23 @@ void CVSymbolDumperImpl::visitCompile3Sy
   W.printString("FrontendVersion", FrontendVersion);
   W.printString("BackendVersion", BackendVersion);
   W.printString("VersionName", Compile3.Version);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
-                                          ConstantSym &Constant) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ConstantSym &Constant) {
   DictScope S(W, "Constant");
 
   CVTD.printTypeIndex("Type", Constant.Header.Type);
   W.printNumber("Value", Constant.Value);
   W.printString("Name", Constant.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
   DictScope S(W, "DataSym");
 
-  W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
+  W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
   StringRef LinkageName;
   if (ObjDelegate) {
     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
@@ -289,27 +308,30 @@ void CVSymbolDumperImpl::visitDataSym(Sy
   W.printString("DisplayName", Data.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
-    SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR,
     DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
   DictScope S(W, "DefRangeFramePointerRelFullScope");
   W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
-    SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
   DictScope S(W, "DefRangeFramePointerRel");
 
   W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
   printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
                               DefRangeFramePointerRel.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
-    SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
   DictScope S(W, "DefRangeRegisterRel");
 
   W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
@@ -321,10 +343,11 @@ void CVSymbolDumperImpl::visitDefRangeRe
   printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
                               DefRangeRegisterRel.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeRegisterSym(
-    SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
   DictScope S(W, "DefRangeRegister");
 
   W.printNumber("Register", DefRangeRegister.Header.Register);
@@ -332,10 +355,11 @@ void CVSymbolDumperImpl::visitDefRangeRe
   printLocalVariableAddrRange(DefRangeRegister.Header.Range,
                               DefRangeRegister.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeRegister.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
-    SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
   DictScope S(W, "DefRangeSubfieldRegister");
 
   W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
@@ -345,17 +369,19 @@ void CVSymbolDumperImpl::visitDefRangeSu
   printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
                               DefRangeSubfieldRegister.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
-    SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
   DictScope S(W, "DefRangeSubfield");
 
   if (ObjDelegate) {
     StringRef StringTable = ObjDelegate->getStringTable();
     auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
     if (ProgramStringTableOffset >= StringTable.size())
-      return parseError();
+      return llvm::make_error<CodeViewError>(
+          "String table offset outside of bounds of String Table!");
     StringRef Program =
         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
     W.printString("Program", Program);
@@ -364,17 +390,19 @@ void CVSymbolDumperImpl::visitDefRangeSu
   printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
                               DefRangeSubfield.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeSubfield.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
-                                          DefRangeSym &DefRange) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           DefRangeSym &DefRange) {
   DictScope S(W, "DefRange");
 
   if (ObjDelegate) {
     StringRef StringTable = ObjDelegate->getStringTable();
     auto ProgramStringTableOffset = DefRange.Header.Program;
     if (ProgramStringTableOffset >= StringTable.size())
-      return parseError();
+      return llvm::make_error<CodeViewError>(
+          "String table offset outside of bounds of String Table!");
     StringRef Program =
         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
     W.printString("Program", Program);
@@ -382,10 +410,11 @@ void CVSymbolDumperImpl::visitDefRangeSy
   printLocalVariableAddrRange(DefRange.Header.Range,
                               DefRange.getRelocationOffset());
   printLocalVariableAddrGap(DefRange.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
-                                             FrameCookieSym &FrameCookie) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FrameCookieSym &FrameCookie) {
   DictScope S(W, "FrameCookie");
 
   StringRef LinkageName;
@@ -398,9 +427,10 @@ void CVSymbolDumperImpl::visitFrameCooki
   W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
               getFrameCookieKindNames());
   W.printHex("Flags", FrameCookie.Header.Flags);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                            FrameProcSym &FrameProc) {
   DictScope S(W, "FrameProc");
 
@@ -414,10 +444,11 @@ void CVSymbolDumperImpl::visitFrameProcS
   W.printHex("SectionIdOfExceptionHandler",
              FrameProc.Header.SectionIdOfExceptionHandler);
   W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
-    SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
   DictScope S(W, "HeapAllocationSite");
 
   StringRef LinkageName;
@@ -431,10 +462,11 @@ void CVSymbolDumperImpl::visitHeapAlloca
   CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
-                                            InlineSiteSym &InlineSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           InlineSiteSym &InlineSite) {
   DictScope S(W, "InlineSite");
 
   W.printHex("PtrParent", InlineSite.Header.PtrParent);
@@ -445,7 +477,8 @@ void CVSymbolDumperImpl::visitInlineSite
   for (auto &Annotation : InlineSite.annotations()) {
     switch (Annotation.OpCode) {
     case BinaryAnnotationsOpCode::Invalid:
-      return parseError();
+      return llvm::make_error<CodeViewError>(
+          "Invalid binary annotation opcode!");
     case BinaryAnnotationsOpCode::CodeOffset:
     case BinaryAnnotationsOpCode::ChangeCodeOffset:
     case BinaryAnnotationsOpCode::ChangeCodeLength:
@@ -486,34 +519,37 @@ void CVSymbolDumperImpl::visitInlineSite
     }
     }
   }
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
-                                          RegisterSym &Register) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           RegisterSym &Register) {
   DictScope S(W, "RegisterSym");
   W.printNumber("Type", Register.Header.Index);
   W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
   W.printString("Name", Register.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
-                                          PublicSym32 &Public) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
   DictScope S(W, "PublicSym");
   W.printNumber("Type", Public.Header.Index);
   W.printNumber("Seg", Public.Header.Seg);
   W.printNumber("Off", Public.Header.Off);
   W.printString("Name", Public.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
   DictScope S(W, "ProcRef");
   W.printNumber("SumName", ProcRef.Header.SumName);
   W.printNumber("SymOffset", ProcRef.Header.SymOffset);
   W.printNumber("Mod", ProcRef.Header.Mod);
   W.printString("Name", ProcRef.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
   DictScope S(W, "Label");
 
   StringRef LinkageName;
@@ -527,33 +563,37 @@ void CVSymbolDumperImpl::visitLabelSym(S
   W.printString("DisplayName", Label.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
   DictScope S(W, "Local");
 
   CVTD.printTypeIndex("Type", Local.Header.Type);
   W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
   W.printString("VarName", Local.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
   DictScope S(W, "ObjectName");
 
   W.printHex("Signature", ObjName.Header.Signature);
   W.printString("ObjectName", ObjName.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
   DictScope S(W, "ProcStart");
 
   if (InFunctionScope)
-    return parseError();
+    return llvm::make_error<CodeViewError>(
+        "Visiting a ProcSym while inside function scope!");
 
   InFunctionScope = true;
 
   StringRef LinkageName;
-  W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
+  W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
   W.printHex("PtrParent", Proc.Header.PtrParent);
   W.printHex("PtrEnd", Proc.Header.PtrEnd);
   W.printHex("PtrNext", Proc.Header.PtrNext);
@@ -571,38 +611,42 @@ void CVSymbolDumperImpl::visitProcSym(Sy
   W.printString("DisplayName", Proc.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
-                                          ScopeEndSym &ScopeEnd) {
-  if (Kind == SymbolKind::S_END)
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ScopeEndSym &ScopeEnd) {
+  if (CVR.kind() == SymbolKind::S_END)
     DictScope S(W, "BlockEnd");
-  else if (Kind == SymbolKind::S_PROC_ID_END)
+  else if (CVR.kind() == SymbolKind::S_PROC_ID_END)
     DictScope S(W, "ProcEnd");
-  else if (Kind == SymbolKind::S_INLINESITE_END)
+  else if (CVR.kind() == SymbolKind::S_INLINESITE_END)
     DictScope S(W, "InlineSiteEnd");
 
   InFunctionScope = false;
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
-  ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+  ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
   for (auto FuncID : Caller.Indices)
     CVTD.printTypeIndex("FuncID", FuncID);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
-                                             RegRelativeSym &RegRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           RegRelativeSym &RegRel) {
   DictScope S(W, "RegRelativeSym");
 
   W.printHex("Offset", RegRel.Header.Offset);
   CVTD.printTypeIndex("Type", RegRel.Header.Type);
   W.printHex("Register", RegRel.Header.Register);
   W.printString("VarName", RegRel.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
-                                                 ThreadLocalDataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ThreadLocalDataSym &Data) {
   DictScope S(W, "ThreadLocalDataSym");
 
   StringRef LinkageName;
@@ -614,29 +658,41 @@ void CVSymbolDumperImpl::visitThreadLoca
   W.printString("DisplayName", Data.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
   DictScope S(W, "UDT");
   CVTD.printTypeIndex("Type", UDT.Header.Type);
   W.printString("UDTName", UDT.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
-                                            ArrayRef<uint8_t> Data) {
+Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
   DictScope S(W, "UnknownSym");
-  W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
-  W.printNumber("Length", uint32_t(Data.size()));
+  W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
+  W.printNumber("Length", CVR.length());
+  return Error::success();
 }
 
-bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
+Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
+  SymbolVisitorCallbackPipeline Pipeline;
+  SymbolDeserializer Deserializer(ObjDelegate.get());
   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
-  Dumper.visitSymbolRecord(Record);
-  return !Dumper.hadError();
+
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(Dumper);
+  CVSymbolVisitor Visitor(Pipeline);
+  return Visitor.visitSymbolRecord(Record);
 }
 
-bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+  SymbolVisitorCallbackPipeline Pipeline;
+  SymbolDeserializer Deserializer(ObjDelegate.get());
   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
-  Dumper.visitSymbolStream(Symbols);
-  return !Dumper.hadError();
+
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(Dumper);
+  CVSymbolVisitor Visitor(Pipeline);
+  return Visitor.visitSymbolStream(Symbols);
 }

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Fri Oct  7 16:34:46 2016
@@ -598,11 +598,15 @@ Error LLVMOutputStyle::dumpDbiStream() {
           ListScope SS(P, "Symbols");
           codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
           bool HadError = false;
-          for (const auto &S : ModS.symbols(&HadError)) {
-            DictScope DD(P, "");
-
-            if (opts::raw::DumpModuleSyms)
-              SD.dump(S);
+          for (auto S : ModS.symbols(&HadError)) {
+            DictScope LL(P, "");
+            if (opts::raw::DumpModuleSyms) {
+              if (auto EC = SD.dump(S)) {
+                llvm::consumeError(std::move(EC));
+                HadError = true;
+                break;
+              }
+            }
             if (opts::raw::DumpSymRecordBytes)
               P.printBinaryBlock("Bytes", S.content());
           }
@@ -811,7 +815,10 @@ Error LLVMOutputStyle::dumpPublicsStream
   for (auto S : Publics->getSymbols(&HadError)) {
     DictScope DD(P, "");
 
-    SD.dump(S);
+    if (auto EC = SD.dump(S)) {
+      HadError = true;
+      break;
+    }
     if (opts::raw::DumpSymRecordBytes)
       P.printBinaryBlock("Bytes", S.content());
   }

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=283609&r1=283608&r2=283609&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Fri Oct  7 16:34:46 2016
@@ -26,6 +26,7 @@
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -965,9 +966,9 @@ void COFFDumper::printCodeViewSymbolsSub
     error(object_error::parse_failed);
   }
 
-  if (!CVSD.dump(Symbols)) {
+  if (auto EC = CVSD.dump(Symbols)) {
     W.flush();
-    error(object_error::parse_failed);
+    error(std::move(EC));
   }
   W.flush();
 }




More information about the llvm-commits mailing list