10b57cec5SDimitry Andric //===- SymbolRecordHelpers.cpp ----------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
100b57cec5SDimitry Andric 
1181ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
120b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric using namespace llvm::codeview;
160b57cec5SDimitry Andric 
createRecord(const CVSymbol & sym)17480093f4SDimitry Andric template <typename RecordT> static RecordT createRecord(const CVSymbol &sym) {
180b57cec5SDimitry Andric   RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
190b57cec5SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
200b57cec5SDimitry Andric   return record;
210b57cec5SDimitry Andric }
220b57cec5SDimitry Andric 
getScopeEndOffset(const CVSymbol & Sym)230b57cec5SDimitry Andric uint32_t llvm::codeview::getScopeEndOffset(const CVSymbol &Sym) {
240b57cec5SDimitry Andric   assert(symbolOpensScope(Sym.kind()));
250b57cec5SDimitry Andric   switch (Sym.kind()) {
260b57cec5SDimitry Andric   case SymbolKind::S_GPROC32:
270b57cec5SDimitry Andric   case SymbolKind::S_LPROC32:
280b57cec5SDimitry Andric   case SymbolKind::S_GPROC32_ID:
290b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_ID:
300b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_DPC:
310b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_DPC_ID: {
320b57cec5SDimitry Andric     ProcSym Proc = createRecord<ProcSym>(Sym);
330b57cec5SDimitry Andric     return Proc.End;
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric   case SymbolKind::S_BLOCK32: {
360b57cec5SDimitry Andric     BlockSym Block = createRecord<BlockSym>(Sym);
370b57cec5SDimitry Andric     return Block.End;
380b57cec5SDimitry Andric   }
390b57cec5SDimitry Andric   case SymbolKind::S_THUNK32: {
400b57cec5SDimitry Andric     Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym);
410b57cec5SDimitry Andric     return Thunk.End;
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric   case SymbolKind::S_INLINESITE: {
440b57cec5SDimitry Andric     InlineSiteSym Site = createRecord<InlineSiteSym>(Sym);
450b57cec5SDimitry Andric     return Site.End;
460b57cec5SDimitry Andric   }
470b57cec5SDimitry Andric   default:
480b57cec5SDimitry Andric     assert(false && "Unknown record type");
490b57cec5SDimitry Andric     return 0;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric uint32_t
getScopeParentOffset(const llvm::codeview::CVSymbol & Sym)540b57cec5SDimitry Andric llvm::codeview::getScopeParentOffset(const llvm::codeview::CVSymbol &Sym) {
550b57cec5SDimitry Andric   assert(symbolOpensScope(Sym.kind()));
560b57cec5SDimitry Andric   switch (Sym.kind()) {
570b57cec5SDimitry Andric   case SymbolKind::S_GPROC32:
580b57cec5SDimitry Andric   case SymbolKind::S_LPROC32:
590b57cec5SDimitry Andric   case SymbolKind::S_GPROC32_ID:
600b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_ID:
610b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_DPC:
620b57cec5SDimitry Andric   case SymbolKind::S_LPROC32_DPC_ID: {
630b57cec5SDimitry Andric     ProcSym Proc = createRecord<ProcSym>(Sym);
640b57cec5SDimitry Andric     return Proc.Parent;
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric   case SymbolKind::S_BLOCK32: {
670b57cec5SDimitry Andric     BlockSym Block = createRecord<BlockSym>(Sym);
680b57cec5SDimitry Andric     return Block.Parent;
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric   case SymbolKind::S_THUNK32: {
710b57cec5SDimitry Andric     Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym);
720b57cec5SDimitry Andric     return Thunk.Parent;
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric   case SymbolKind::S_INLINESITE: {
750b57cec5SDimitry Andric     InlineSiteSym Site = createRecord<InlineSiteSym>(Sym);
760b57cec5SDimitry Andric     return Site.Parent;
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric   default:
790b57cec5SDimitry Andric     assert(false && "Unknown record type");
800b57cec5SDimitry Andric     return 0;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric CVSymbolArray
limitSymbolArrayToScope(const CVSymbolArray & Symbols,uint32_t ScopeBegin)850b57cec5SDimitry Andric llvm::codeview::limitSymbolArrayToScope(const CVSymbolArray &Symbols,
860b57cec5SDimitry Andric                                         uint32_t ScopeBegin) {
870b57cec5SDimitry Andric   CVSymbol Opener = *Symbols.at(ScopeBegin);
880b57cec5SDimitry Andric   assert(symbolOpensScope(Opener.kind()));
890b57cec5SDimitry Andric   uint32_t EndOffset = getScopeEndOffset(Opener);
900b57cec5SDimitry Andric   CVSymbol Closer = *Symbols.at(EndOffset);
910b57cec5SDimitry Andric   EndOffset += Closer.RecordData.size();
920b57cec5SDimitry Andric   return Symbols.substream(ScopeBegin, EndOffset);
930b57cec5SDimitry Andric }
94