10d840744SZachary Turner //===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
20d840744SZachary Turner //
30d840744SZachary Turner //                     The LLVM Compiler Infrastructure
40d840744SZachary Turner //
50d840744SZachary Turner // This file is distributed under the University of Illinois Open Source
60d840744SZachary Turner // License. See LICENSE.TXT for details.
70d840744SZachary Turner //
80d840744SZachary Turner //===----------------------------------------------------------------------===//
90d840744SZachary Turner 
100d840744SZachary Turner #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
110d840744SZachary Turner 
120d840744SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
130d840744SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
140d840744SZachary Turner 
150d840744SZachary Turner using namespace llvm;
160d840744SZachary Turner using namespace llvm::codeview;
170d840744SZachary Turner 
180d840744SZachary Turner CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
190d840744SZachary Turner     : Callbacks(Callbacks) {}
200d840744SZachary Turner 
210d840744SZachary Turner template <typename T>
220d840744SZachary Turner static Error visitKnownRecord(CVSymbol &Record,
230d840744SZachary Turner                               SymbolVisitorCallbacks &Callbacks) {
240d840744SZachary Turner   SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
250d840744SZachary Turner   T KnownRecord(RK);
260d840744SZachary Turner   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
270d840744SZachary Turner     return EC;
280d840744SZachary Turner   return Error::success();
290d840744SZachary Turner }
300d840744SZachary Turner 
31af8c75a8SZachary Turner static Error finishVisitation(CVSymbol &Record,
32af8c75a8SZachary Turner                               SymbolVisitorCallbacks &Callbacks) {
330d840744SZachary Turner   switch (Record.Type) {
340d840744SZachary Turner   default:
350d840744SZachary Turner     if (auto EC = Callbacks.visitUnknownSymbol(Record))
360d840744SZachary Turner       return EC;
370d840744SZachary Turner     break;
380d840744SZachary Turner #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
390d840744SZachary Turner   case EnumName: {                                                             \
400d840744SZachary Turner     if (auto EC = visitKnownRecord<Name>(Record, Callbacks))                   \
410d840744SZachary Turner       return EC;                                                               \
420d840744SZachary Turner     break;                                                                     \
430d840744SZachary Turner   }
440d840744SZachary Turner #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
450d840744SZachary Turner   SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
46d427383cSZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
470d840744SZachary Turner   }
480d840744SZachary Turner 
490d840744SZachary Turner   if (auto EC = Callbacks.visitSymbolEnd(Record))
500d840744SZachary Turner     return EC;
510d840744SZachary Turner 
520d840744SZachary Turner   return Error::success();
530d840744SZachary Turner }
540d840744SZachary Turner 
55af8c75a8SZachary Turner Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
56af8c75a8SZachary Turner   if (auto EC = Callbacks.visitSymbolBegin(Record))
57af8c75a8SZachary Turner     return EC;
58af8c75a8SZachary Turner   return finishVisitation(Record, Callbacks);
59af8c75a8SZachary Turner }
60af8c75a8SZachary Turner 
61af8c75a8SZachary Turner Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) {
62af8c75a8SZachary Turner   if (auto EC = Callbacks.visitSymbolBegin(Record, Offset))
63af8c75a8SZachary Turner     return EC;
64af8c75a8SZachary Turner   return finishVisitation(Record, Callbacks);
65af8c75a8SZachary Turner }
66af8c75a8SZachary Turner 
670d840744SZachary Turner Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
680d840744SZachary Turner   for (auto I : Symbols) {
690d840744SZachary Turner     if (auto EC = visitSymbolRecord(I))
700d840744SZachary Turner       return EC;
710d840744SZachary Turner   }
720d840744SZachary Turner   return Error::success();
730d840744SZachary Turner }
74af8c75a8SZachary Turner 
75af8c75a8SZachary Turner Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
76af8c75a8SZachary Turner                                          uint32_t InitialOffset) {
77af8c75a8SZachary Turner   for (auto I : Symbols) {
78*579264bdSZachary Turner     if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew()))
79af8c75a8SZachary Turner       return EC;
80af8c75a8SZachary Turner     InitialOffset += I.length();
81af8c75a8SZachary Turner   }
82af8c75a8SZachary Turner   return Error::success();
83af8c75a8SZachary Turner }
84