1d88c1a5aSDimitry Andric //===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric //                     The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric 
10d88c1a5aSDimitry Andric #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
11d88c1a5aSDimitry Andric 
12d88c1a5aSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13d88c1a5aSDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
14d88c1a5aSDimitry Andric 
15d88c1a5aSDimitry Andric using namespace llvm;
16d88c1a5aSDimitry Andric using namespace llvm::codeview;
17d88c1a5aSDimitry Andric 
CVSymbolVisitor(SymbolVisitorCallbacks & Callbacks)18d88c1a5aSDimitry Andric CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
19d88c1a5aSDimitry Andric     : Callbacks(Callbacks) {}
20d88c1a5aSDimitry Andric 
21d88c1a5aSDimitry Andric template <typename T>
visitKnownRecord(CVSymbol & Record,SymbolVisitorCallbacks & Callbacks)22d88c1a5aSDimitry Andric static Error visitKnownRecord(CVSymbol &Record,
23d88c1a5aSDimitry Andric                               SymbolVisitorCallbacks &Callbacks) {
24d88c1a5aSDimitry Andric   SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
25d88c1a5aSDimitry Andric   T KnownRecord(RK);
26d88c1a5aSDimitry Andric   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
27d88c1a5aSDimitry Andric     return EC;
28d88c1a5aSDimitry Andric   return Error::success();
29d88c1a5aSDimitry Andric }
30d88c1a5aSDimitry Andric 
finishVisitation(CVSymbol & Record,SymbolVisitorCallbacks & Callbacks)31a580b014SDimitry Andric static Error finishVisitation(CVSymbol &Record,
32a580b014SDimitry Andric                               SymbolVisitorCallbacks &Callbacks) {
33d88c1a5aSDimitry Andric   switch (Record.Type) {
34d88c1a5aSDimitry Andric   default:
35d88c1a5aSDimitry Andric     if (auto EC = Callbacks.visitUnknownSymbol(Record))
36d88c1a5aSDimitry Andric       return EC;
37d88c1a5aSDimitry Andric     break;
38d88c1a5aSDimitry Andric #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
39d88c1a5aSDimitry Andric   case EnumName: {                                                             \
40d88c1a5aSDimitry Andric     if (auto EC = visitKnownRecord<Name>(Record, Callbacks))                   \
41d88c1a5aSDimitry Andric       return EC;                                                               \
42d88c1a5aSDimitry Andric     break;                                                                     \
43d88c1a5aSDimitry Andric   }
44d88c1a5aSDimitry Andric #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
45d88c1a5aSDimitry Andric   SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
46f9448bf3SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
47d88c1a5aSDimitry Andric   }
48d88c1a5aSDimitry Andric 
49d88c1a5aSDimitry Andric   if (auto EC = Callbacks.visitSymbolEnd(Record))
50d88c1a5aSDimitry Andric     return EC;
51d88c1a5aSDimitry Andric 
52d88c1a5aSDimitry Andric   return Error::success();
53d88c1a5aSDimitry Andric }
54d88c1a5aSDimitry Andric 
visitSymbolRecord(CVSymbol & Record)55a580b014SDimitry Andric Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
56a580b014SDimitry Andric   if (auto EC = Callbacks.visitSymbolBegin(Record))
57a580b014SDimitry Andric     return EC;
58a580b014SDimitry Andric   return finishVisitation(Record, Callbacks);
59a580b014SDimitry Andric }
60a580b014SDimitry Andric 
visitSymbolRecord(CVSymbol & Record,uint32_t Offset)61a580b014SDimitry Andric Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) {
62a580b014SDimitry Andric   if (auto EC = Callbacks.visitSymbolBegin(Record, Offset))
63a580b014SDimitry Andric     return EC;
64a580b014SDimitry Andric   return finishVisitation(Record, Callbacks);
65a580b014SDimitry Andric }
66a580b014SDimitry Andric 
visitSymbolStream(const CVSymbolArray & Symbols)67d88c1a5aSDimitry Andric Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
68d88c1a5aSDimitry Andric   for (auto I : Symbols) {
69d88c1a5aSDimitry Andric     if (auto EC = visitSymbolRecord(I))
70d88c1a5aSDimitry Andric       return EC;
71d88c1a5aSDimitry Andric   }
72d88c1a5aSDimitry Andric   return Error::success();
73d88c1a5aSDimitry Andric }
74a580b014SDimitry Andric 
visitSymbolStream(const CVSymbolArray & Symbols,uint32_t InitialOffset)75a580b014SDimitry Andric Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
76a580b014SDimitry Andric                                          uint32_t InitialOffset) {
77a580b014SDimitry Andric   for (auto I : Symbols) {
78*b5893f02SDimitry Andric     if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew()))
79a580b014SDimitry Andric       return EC;
80a580b014SDimitry Andric     InitialOffset += I.length();
81a580b014SDimitry Andric   }
82a580b014SDimitry Andric   return Error::success();
83a580b014SDimitry Andric }
84