|  | //===- SymbolRecordHelpers.cpp ----------------------------------*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" | 
|  |  | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::codeview; | 
|  |  | 
|  | template <typename RecordT> static RecordT createRecord(const CVSymbol &sym) { | 
|  | RecordT record(static_cast<SymbolRecordKind>(sym.kind())); | 
|  | cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record)); | 
|  | return record; | 
|  | } | 
|  |  | 
|  | uint32_t llvm::codeview::getScopeEndOffset(const CVSymbol &Sym) { | 
|  | assert(symbolOpensScope(Sym.kind())); | 
|  | switch (Sym.kind()) { | 
|  | case SymbolKind::S_GPROC32: | 
|  | case SymbolKind::S_LPROC32: | 
|  | case SymbolKind::S_GPROC32_ID: | 
|  | case SymbolKind::S_LPROC32_ID: | 
|  | case SymbolKind::S_LPROC32_DPC: | 
|  | case SymbolKind::S_LPROC32_DPC_ID: { | 
|  | ProcSym Proc = createRecord<ProcSym>(Sym); | 
|  | return Proc.End; | 
|  | } | 
|  | case SymbolKind::S_BLOCK32: { | 
|  | BlockSym Block = createRecord<BlockSym>(Sym); | 
|  | return Block.End; | 
|  | } | 
|  | case SymbolKind::S_THUNK32: { | 
|  | Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym); | 
|  | return Thunk.End; | 
|  | } | 
|  | case SymbolKind::S_INLINESITE: { | 
|  | InlineSiteSym Site = createRecord<InlineSiteSym>(Sym); | 
|  | return Site.End; | 
|  | } | 
|  | default: | 
|  | assert(false && "Unknown record type"); | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | uint32_t | 
|  | llvm::codeview::getScopeParentOffset(const llvm::codeview::CVSymbol &Sym) { | 
|  | assert(symbolOpensScope(Sym.kind())); | 
|  | switch (Sym.kind()) { | 
|  | case SymbolKind::S_GPROC32: | 
|  | case SymbolKind::S_LPROC32: | 
|  | case SymbolKind::S_GPROC32_ID: | 
|  | case SymbolKind::S_LPROC32_ID: | 
|  | case SymbolKind::S_LPROC32_DPC: | 
|  | case SymbolKind::S_LPROC32_DPC_ID: { | 
|  | ProcSym Proc = createRecord<ProcSym>(Sym); | 
|  | return Proc.Parent; | 
|  | } | 
|  | case SymbolKind::S_BLOCK32: { | 
|  | BlockSym Block = createRecord<BlockSym>(Sym); | 
|  | return Block.Parent; | 
|  | } | 
|  | case SymbolKind::S_THUNK32: { | 
|  | Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym); | 
|  | return Thunk.Parent; | 
|  | } | 
|  | case SymbolKind::S_INLINESITE: { | 
|  | InlineSiteSym Site = createRecord<InlineSiteSym>(Sym); | 
|  | return Site.Parent; | 
|  | } | 
|  | default: | 
|  | assert(false && "Unknown record type"); | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | CVSymbolArray | 
|  | llvm::codeview::limitSymbolArrayToScope(const CVSymbolArray &Symbols, | 
|  | uint32_t ScopeBegin) { | 
|  | CVSymbol Opener = *Symbols.at(ScopeBegin); | 
|  | assert(symbolOpensScope(Opener.kind())); | 
|  | uint32_t EndOffset = getScopeEndOffset(Opener); | 
|  | CVSymbol Closer = *Symbols.at(EndOffset); | 
|  | EndOffset += Closer.RecordData.size(); | 
|  | return Symbols.substream(ScopeBegin, EndOffset); | 
|  | } |