LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - TypeIndexDiscovery.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 181 245 73.9 %
Date: 2018-10-20 13:21:21 Functions: 10 25 40.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TypeIndexDiscovery.cpp -----------------------------------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
      10             : 
      11             : #include "llvm/ADT/ArrayRef.h"
      12             : #include "llvm/Support/Endian.h"
      13             : 
      14             : using namespace llvm;
      15             : using namespace llvm::codeview;
      16             : 
      17             : static inline MethodKind getMethodKind(uint16_t Attrs) {
      18         161 :   Attrs &= uint16_t(MethodOptions::MethodKindMask);
      19         161 :   Attrs >>= 2;
      20         161 :   return MethodKind(Attrs);
      21             : }
      22             : 
      23             : static inline bool isIntroVirtual(uint16_t Attrs) {
      24             :   MethodKind MK = getMethodKind(Attrs);
      25         161 :   return MK == MethodKind::IntroducingVirtual ||
      26         161 :          MK == MethodKind::PureIntroducingVirtual;
      27             : }
      28             : 
      29             : static inline PointerMode getPointerMode(uint32_t Attrs) {
      30           0 :   return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
      31           0 :                                   PointerRecord::PointerModeMask);
      32             : }
      33             : 
      34             : static inline bool isMemberPointer(uint32_t Attrs) {
      35             :   PointerMode Mode = getPointerMode(Attrs);
      36           0 :   return Mode == PointerMode::PointerToDataMember ||
      37             :          Mode == PointerMode::PointerToMemberFunction;
      38             : }
      39             : 
      40           0 : static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
      41           0 :   uint16_t N = support::endian::read16le(Data.data());
      42          18 :   if (N < LF_NUMERIC)
      43           0 :     return 2;
      44             : 
      45             :   assert(N <= LF_UQUADWORD);
      46             : 
      47           0 :   constexpr uint32_t Sizes[] = {
      48             :       1,  // LF_CHAR
      49             :       2,  // LF_SHORT
      50             :       2,  // LF_USHORT
      51             :       4,  // LF_LONG
      52             :       4,  // LF_ULONG
      53             :       4,  // LF_REAL32
      54             :       8,  // LF_REAL64
      55             :       10, // LF_REAL80
      56             :       16, // LF_REAL128
      57             :       8,  // LF_QUADWORD
      58             :       8,  // LF_UQUADWORD
      59             :   };
      60             : 
      61           0 :   return 2 + Sizes[N - LF_NUMERIC];
      62             : }
      63             : 
      64           0 : static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) {
      65           0 :   const char *S = reinterpret_cast<const char *>(Data.data());
      66           0 :   return strlen(S) + 1;
      67             : }
      68             : 
      69          67 : static void handleMethodOverloadList(ArrayRef<uint8_t> Content,
      70             :                                      SmallVectorImpl<TiReference> &Refs) {
      71             :   uint32_t Offset = 0;
      72             : 
      73         228 :   while (!Content.empty()) {
      74             :     // Array of:
      75             :     //   0: Attrs
      76             :     //   2: Padding
      77             :     //   4: TypeIndex
      78             :     //   if (isIntroVirtual())
      79             :     //     8: VFTableOffset
      80             : 
      81             :     // At least 8 bytes are guaranteed.  4 extra bytes come iff function is an
      82             :     // intro virtual.
      83             :     uint32_t Len = 8;
      84             : 
      85             :     uint16_t Attrs = support::endian::read16le(Content.data());
      86         161 :     Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
      87             : 
      88         161 :     if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
      89             :       Len += 4;
      90         161 :     Offset += Len;
      91         161 :     Content = Content.drop_front(Len);
      92             :   }
      93          67 : }
      94             : 
      95           0 : static uint32_t handleBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
      96             :                                 SmallVectorImpl<TiReference> &Refs) {
      97             :   // 0: Kind
      98             :   // 2: Padding
      99             :   // 4: TypeIndex
     100             :   // 8: Encoded Integer
     101           0 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     102           0 :   return 8 + getEncodedIntegerLength(Data.drop_front(8));
     103             : }
     104             : 
     105           0 : static uint32_t handleEnumerator(ArrayRef<uint8_t> Data, uint32_t Offset,
     106             :                                  SmallVectorImpl<TiReference> &Refs) {
     107             :   // 0: Kind
     108             :   // 2: Padding
     109             :   // 4: Encoded Integer
     110             :   // <next>: Name
     111           0 :   uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
     112           0 :   return Size + getCStringLength(Data.drop_front(Size));
     113             : }
     114             : 
     115           0 : static uint32_t handleDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
     116             :                                  SmallVectorImpl<TiReference> &Refs) {
     117             :   // 0: Kind
     118             :   // 2: Padding
     119             :   // 4: TypeIndex
     120             :   // 8: Encoded Integer
     121             :   // <next>: Name
     122           0 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     123           0 :   uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
     124           0 :   return Size + getCStringLength(Data.drop_front(Size));
     125             : }
     126             : 
     127           0 : static uint32_t handleOverloadedMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
     128             :                                        SmallVectorImpl<TiReference> &Refs) {
     129             :   // 0: Kind
     130             :   // 2: Padding
     131             :   // 4: TypeIndex
     132             :   // 8: Name
     133           0 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     134           0 :   return 8 + getCStringLength(Data.drop_front(8));
     135             : }
     136             : 
     137           0 : static uint32_t handleOneMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
     138             :                                 SmallVectorImpl<TiReference> &Refs) {
     139             :   // 0: Kind
     140             :   // 2: Attributes
     141             :   // 4: Type
     142             :   // if (isIntroVirtual)
     143             :   //   8: VFTableOffset
     144             :   // <next>: Name
     145             :   uint32_t Size = 8;
     146           0 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     147             : 
     148           0 :   uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
     149           0 :   if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
     150             :     Size += 4;
     151             : 
     152           0 :   return Size + getCStringLength(Data.drop_front(Size));
     153             : }
     154             : 
     155           0 : static uint32_t handleNestedType(ArrayRef<uint8_t> Data, uint32_t Offset,
     156             :                                  SmallVectorImpl<TiReference> &Refs) {
     157             :   // 0: Kind
     158             :   // 2: Padding
     159             :   // 4: TypeIndex
     160             :   // 8: Name
     161           0 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     162           0 :   return 8 + getCStringLength(Data.drop_front(8));
     163             : }
     164             : 
     165           0 : static uint32_t handleStaticDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
     166             :                                        SmallVectorImpl<TiReference> &Refs) {
     167             :   // 0: Kind
     168             :   // 2: Padding
     169             :   // 4: TypeIndex
     170             :   // 8: Name
     171           0 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     172           0 :   return 8 + getCStringLength(Data.drop_front(8));
     173             : }
     174             : 
     175          18 : static uint32_t handleVirtualBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
     176             :                                        bool IsIndirect,
     177             :                                        SmallVectorImpl<TiReference> &Refs) {
     178             :   // 0: Kind
     179             :   // 2: Attrs
     180             :   // 4: TypeIndex
     181             :   // 8: TypeIndex
     182             :   // 12: Encoded Integer
     183             :   // <next>: Encoded Integer
     184             :   uint32_t Size = 12;
     185          18 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 2});
     186          18 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     187          18 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     188          18 :   return Size;
     189             : }
     190             : 
     191           0 : static uint32_t handleVFPtr(ArrayRef<uint8_t> Data, uint32_t Offset,
     192             :                             SmallVectorImpl<TiReference> &Refs) {
     193             :   // 0: Kind
     194             :   // 2: Padding
     195             :   // 4: TypeIndex
     196          20 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     197           0 :   return 8;
     198             : }
     199             : 
     200           0 : static uint32_t handleListContinuation(ArrayRef<uint8_t> Data, uint32_t Offset,
     201             :                                        SmallVectorImpl<TiReference> &Refs) {
     202             :   // 0: Kind
     203             :   // 2: Padding
     204             :   // 4: TypeIndex
     205           6 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     206           0 :   return 8;
     207             : }
     208             : 
     209         289 : static void handleFieldList(ArrayRef<uint8_t> Content,
     210             :                             SmallVectorImpl<TiReference> &Refs) {
     211             :   uint32_t Offset = 0;
     212             :   uint32_t ThisLen = 0;
     213        7132 :   while (!Content.empty()) {
     214             :     TypeLeafKind Kind =
     215             :         static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
     216        6843 :     switch (Kind) {
     217          26 :     case LF_BCLASS:
     218          26 :       ThisLen = handleBaseClass(Content, Offset, Refs);
     219          26 :       break;
     220        6163 :     case LF_ENUMERATE:
     221        6163 :       ThisLen = handleEnumerator(Content, Offset, Refs);
     222        6163 :       break;
     223         339 :     case LF_MEMBER:
     224         339 :       ThisLen = handleDataMember(Content, Offset, Refs);
     225         339 :       break;
     226          67 :     case LF_METHOD:
     227          67 :       ThisLen = handleOverloadedMethod(Content, Offset, Refs);
     228          67 :       break;
     229         114 :     case LF_ONEMETHOD:
     230         114 :       ThisLen = handleOneMethod(Content, Offset, Refs);
     231         114 :       break;
     232          81 :     case LF_NESTTYPE:
     233          81 :       ThisLen = handleNestedType(Content, Offset, Refs);
     234          81 :       break;
     235           9 :     case LF_STMEMBER:
     236           9 :       ThisLen = handleStaticDataMember(Content, Offset, Refs);
     237           9 :       break;
     238          18 :     case LF_VBCLASS:
     239             :     case LF_IVBCLASS:
     240             :       ThisLen =
     241          18 :           handleVirtualBaseClass(Content, Offset, Kind == LF_VBCLASS, Refs);
     242          18 :       break;
     243             :     case LF_VFUNCTAB:
     244             :       ThisLen = handleVFPtr(Content, Offset, Refs);
     245          20 :       break;
     246             :     case LF_INDEX:
     247             :       ThisLen = handleListContinuation(Content, Offset, Refs);
     248           6 :       break;
     249             :     default:
     250             :       return;
     251             :     }
     252        6843 :     Content = Content.drop_front(ThisLen);
     253        6843 :     Offset += ThisLen;
     254        6843 :     if (!Content.empty()) {
     255        6743 :       uint8_t Pad = Content.front();
     256        6743 :       if (Pad >= LF_PAD0) {
     257        1802 :         uint32_t Skip = Pad & 0x0F;
     258        1802 :         Content = Content.drop_front(Skip);
     259        1802 :         Offset += Skip;
     260             :       }
     261             :     }
     262             :   }
     263             : }
     264             : 
     265           0 : static void handlePointer(ArrayRef<uint8_t> Content,
     266             :                           SmallVectorImpl<TiReference> &Refs) {
     267           0 :   Refs.push_back({TiRefKind::TypeRef, 0, 1});
     268             : 
     269           0 :   uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
     270           0 :   if (isMemberPointer(Attrs))
     271           0 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     272           0 : }
     273             : 
     274        3994 : static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
     275             :                                 SmallVectorImpl<TiReference> &Refs) {
     276             :   uint32_t Count;
     277             :   // FIXME: In the future it would be nice if we could avoid hardcoding these
     278             :   // values.  One idea is to define some structures representing these types
     279             :   // that would allow the use of offsetof().
     280        3994 :   switch (Kind) {
     281         365 :   case TypeLeafKind::LF_FUNC_ID:
     282         365 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     283         365 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     284         365 :     break;
     285          75 :   case TypeLeafKind::LF_MFUNC_ID:
     286          75 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     287          75 :     break;
     288         652 :   case TypeLeafKind::LF_STRING_ID:
     289         652 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     290         652 :     break;
     291          42 :   case TypeLeafKind::LF_SUBSTR_LIST:
     292             :     Count = support::endian::read32le(Content.data());
     293          42 :     if (Count > 0)
     294          42 :       Refs.push_back({TiRefKind::IndexRef, 4, Count});
     295             :     break;
     296         173 :   case TypeLeafKind::LF_BUILDINFO:
     297         173 :     Count = support::endian::read16le(Content.data());
     298         173 :     if (Count > 0)
     299         173 :       Refs.push_back({TiRefKind::IndexRef, 2, Count});
     300             :     break;
     301         246 :   case TypeLeafKind::LF_UDT_SRC_LINE:
     302         246 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     303         246 :     Refs.push_back({TiRefKind::IndexRef, 4, 1});
     304         246 :     break;
     305           9 :   case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
     306           9 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     307           9 :     break;
     308         106 :   case TypeLeafKind::LF_MODIFIER:
     309         106 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     310         106 :     break;
     311         267 :   case TypeLeafKind::LF_PROCEDURE:
     312         267 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     313         267 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     314         267 :     break;
     315         293 :   case TypeLeafKind::LF_MFUNCTION:
     316         293 :     Refs.push_back({TiRefKind::TypeRef, 0, 3});
     317         293 :     Refs.push_back({TiRefKind::TypeRef, 16, 1});
     318         293 :     break;
     319         467 :   case TypeLeafKind::LF_ARGLIST:
     320             :     Count = support::endian::read32le(Content.data());
     321         467 :     if (Count > 0)
     322         244 :       Refs.push_back({TiRefKind::TypeRef, 4, Count});
     323             :     break;
     324          28 :   case TypeLeafKind::LF_ARRAY:
     325          28 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     326          28 :     break;
     327         384 :   case TypeLeafKind::LF_CLASS:
     328             :   case TypeLeafKind::LF_STRUCTURE:
     329             :   case TypeLeafKind::LF_INTERFACE:
     330         384 :     Refs.push_back({TiRefKind::TypeRef, 4, 3});
     331         384 :     break;
     332          21 :   case TypeLeafKind::LF_UNION:
     333          21 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     334          21 :     break;
     335          77 :   case TypeLeafKind::LF_ENUM:
     336          77 :     Refs.push_back({TiRefKind::TypeRef, 4, 2});
     337          77 :     break;
     338          14 :   case TypeLeafKind::LF_BITFIELD:
     339          14 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     340          14 :     break;
     341           8 :   case TypeLeafKind::LF_VFTABLE:
     342           8 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     343           8 :     break;
     344             :   case TypeLeafKind::LF_VTSHAPE:
     345             :     break;
     346          67 :   case TypeLeafKind::LF_METHODLIST:
     347          67 :     handleMethodOverloadList(Content, Refs);
     348          67 :     break;
     349         289 :   case TypeLeafKind::LF_FIELDLIST:
     350         289 :     handleFieldList(Content, Refs);
     351         289 :     break;
     352         388 :   case TypeLeafKind::LF_POINTER:
     353         388 :     handlePointer(Content, Refs);
     354         388 :     break;
     355             :   default:
     356             :     break;
     357             :   }
     358        3994 : }
     359             : 
     360         645 : static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind,
     361             :                                 SmallVectorImpl<TiReference> &Refs) {
     362             :   uint32_t Count;
     363             :   // FIXME: In the future it would be nice if we could avoid hardcoding these
     364             :   // values.  One idea is to define some structures representing these types
     365             :   // that would allow the use of offsetof().
     366         645 :   switch (Kind) {
     367         150 :   case SymbolKind::S_GPROC32:
     368             :   case SymbolKind::S_LPROC32:
     369             :   case SymbolKind::S_GPROC32_ID:
     370             :   case SymbolKind::S_LPROC32_ID:
     371             :   case SymbolKind::S_LPROC32_DPC:
     372             :   case SymbolKind::S_LPROC32_DPC_ID:
     373         150 :     Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
     374         150 :     break;
     375          94 :   case SymbolKind::S_UDT:
     376          94 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
     377          94 :     break;
     378          20 :   case SymbolKind::S_GDATA32:
     379             :   case SymbolKind::S_LDATA32:
     380          20 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     381          20 :     break;
     382          36 :   case SymbolKind::S_BUILDINFO:
     383          36 :     Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
     384          36 :     break;
     385           0 :   case SymbolKind::S_LTHREAD32:
     386             :   case SymbolKind::S_GTHREAD32:
     387           0 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     388           0 :     break;
     389           3 :   case SymbolKind::S_FILESTATIC:
     390           3 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     391           3 :     break;
     392          37 :   case SymbolKind::S_LOCAL:
     393          37 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     394          37 :     break;
     395           1 :   case SymbolKind::S_REGISTER:
     396           1 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     397           1 :     break;
     398           0 :   case SymbolKind::S_CONSTANT:
     399           0 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     400           0 :     break;
     401          22 :   case SymbolKind::S_BPREL32:
     402             :   case SymbolKind::S_REGREL32:
     403          22 :     Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
     404          22 :     break;
     405           0 :   case SymbolKind::S_CALLSITEINFO:
     406           0 :     Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature
     407           0 :     break;
     408           7 :   case SymbolKind::S_CALLERS:
     409             :   case SymbolKind::S_CALLEES:
     410             :   case SymbolKind::S_INLINEES:
     411             :     // The record is a count followed by an array of type indices.
     412           7 :     Count = *reinterpret_cast<const ulittle32_t *>(Content.data());
     413           7 :     Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees
     414           7 :     break;
     415           1 :   case SymbolKind::S_INLINESITE:
     416           1 :     Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee
     417           1 :     break;
     418           1 :   case SymbolKind::S_HEAPALLOCSITE:
     419           1 :     Refs.push_back({TiRefKind::TypeRef, 8, 1}); // UDT allocated
     420           1 :     break;
     421             : 
     422             :   // Defranges don't have types, just registers and code offsets.
     423             :   case SymbolKind::S_DEFRANGE_REGISTER:
     424             :   case SymbolKind::S_DEFRANGE_REGISTER_REL:
     425             :   case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
     426             :   case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
     427             :   case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
     428             :   case SymbolKind::S_DEFRANGE_SUBFIELD:
     429             :     break;
     430             : 
     431             :   // No type references.
     432             :   case SymbolKind::S_LABEL32:
     433             :   case SymbolKind::S_OBJNAME:
     434             :   case SymbolKind::S_COMPILE:
     435             :   case SymbolKind::S_COMPILE2:
     436             :   case SymbolKind::S_COMPILE3:
     437             :   case SymbolKind::S_ENVBLOCK:
     438             :   case SymbolKind::S_BLOCK32:
     439             :   case SymbolKind::S_FRAMEPROC:
     440             :   case SymbolKind::S_THUNK32:
     441             :   case SymbolKind::S_FRAMECOOKIE:
     442             :   case SymbolKind::S_UNAMESPACE:
     443             :     break;
     444             :   // Scope ending symbols.
     445             :   case SymbolKind::S_END:
     446             :   case SymbolKind::S_INLINESITE_END:
     447             :   case SymbolKind::S_PROC_ID_END:
     448             :     break;
     449             :   default:
     450             :     return false; // Unknown symbol.
     451             :   }
     452             :   return true;
     453             : }
     454             : 
     455           0 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     456             :                                          SmallVectorImpl<TiReference> &Refs) {
     457           0 :   ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
     458           0 : }
     459             : 
     460         263 : static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
     461             :                                        ArrayRef<TiReference> Refs,
     462             :                                        SmallVectorImpl<TypeIndex> &Indices) {
     463             :   Indices.clear();
     464             : 
     465         263 :   if (Refs.empty())
     466           6 :     return;
     467             : 
     468             :   RecordData = RecordData.drop_front(sizeof(RecordPrefix));
     469             : 
     470         257 :   BinaryStreamReader Reader(RecordData, support::little);
     471         663 :   for (const auto &Ref : Refs) {
     472         406 :     Reader.setOffset(Ref.Offset);
     473             :     FixedStreamArray<TypeIndex> Run;
     474         406 :     cantFail(Reader.readArray(Run, Ref.Count));
     475        1624 :     Indices.append(Run.begin(), Run.end());
     476             :   }
     477             : }
     478             : 
     479         263 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     480             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     481         263 :   return discoverTypeIndices(Type.RecordData, Indices);
     482             : }
     483             : 
     484         263 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     485             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     486             :   SmallVector<TiReference, 4> Refs;
     487         263 :   discoverTypeIndices(RecordData, Refs);
     488         263 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     489         263 : }
     490             : 
     491        3994 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     492             :                                          SmallVectorImpl<TiReference> &Refs) {
     493             :   const RecordPrefix *P =
     494             :       reinterpret_cast<const RecordPrefix *>(RecordData.data());
     495             :   TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
     496        7988 :   ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
     497        3994 : }
     498             : 
     499         645 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     500             :     const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
     501         645 :   SymbolKind K = Sym.kind();
     502        1290 :   return ::discoverTypeIndices(Sym.content(), K, Refs);
     503             : }
     504             : 
     505           0 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     506             :     ArrayRef<uint8_t> RecordData, SmallVectorImpl<TiReference> &Refs) {
     507             :   const RecordPrefix *P =
     508             :       reinterpret_cast<const RecordPrefix *>(RecordData.data());
     509             :   SymbolKind K = static_cast<SymbolKind>(uint16_t(P->RecordKind));
     510           0 :   return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
     511           0 :                                Refs);
     512             : }
     513             : 
     514           0 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     515             :     ArrayRef<uint8_t> RecordData, SmallVectorImpl<TypeIndex> &Indices) {
     516             :   SmallVector<TiReference, 2> Refs;
     517           0 :   if (!discoverTypeIndicesInSymbol(RecordData, Refs))
     518             :     return false;
     519           0 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     520           0 :   return true;
     521             : }

Generated by: LCOV version 1.13