LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - TypeIndexDiscovery.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 216 235 91.9 %
Date: 2018-07-13 00:08:38 Functions: 18 21 85.7 %
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         256 :   Attrs &= uint16_t(MethodOptions::MethodKindMask);
      19         256 :   Attrs >>= 2;
      20         256 :   return MethodKind(Attrs);
      21             : }
      22             : 
      23             : static inline bool isIntroVirtual(uint16_t Attrs) {
      24             :   MethodKind MK = getMethodKind(Attrs);
      25         256 :   return MK == MethodKind::IntroducingVirtual ||
      26         256 :          MK == MethodKind::PureIntroducingVirtual;
      27             : }
      28             : 
      29             : static inline PointerMode getPointerMode(uint32_t Attrs) {
      30         357 :   return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
      31         357 :                                   PointerRecord::PointerModeMask);
      32             : }
      33             : 
      34             : static inline bool isMemberPointer(uint32_t Attrs) {
      35             :   PointerMode Mode = getPointerMode(Attrs);
      36         357 :   return Mode == PointerMode::PointerToDataMember ||
      37             :          Mode == PointerMode::PointerToMemberFunction;
      38             : }
      39             : 
      40             : static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
      41             :   uint16_t N = support::endian::read16le(Data.data());
      42        6477 :   if (N < LF_NUMERIC)
      43             :     return 2;
      44             : 
      45             :   assert(N <= LF_UQUADWORD);
      46             : 
      47          99 :   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          99 :   return 2 + Sizes[N - LF_NUMERIC];
      62             : }
      63             : 
      64             : static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) {
      65             :   const char *S = reinterpret_cast<const char *>(Data.data());
      66        6664 :   return strlen(S) + 1;
      67             : }
      68             : 
      69          62 : static void handleMethodOverloadList(ArrayRef<uint8_t> Content,
      70             :                                      SmallVectorImpl<TiReference> &Refs) {
      71             :   uint32_t Offset = 0;
      72             : 
      73         360 :   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         149 :     Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
      87             : 
      88         149 :     if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
      89             :       Len += 4;
      90         149 :     Offset += Len;
      91         149 :     Content = Content.drop_front(Len);
      92             :   }
      93          62 : }
      94             : 
      95          25 : 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          25 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     102          25 :   return 8 + getEncodedIntegerLength(Data.drop_front(8));
     103             : }
     104             : 
     105        6101 : 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        6101 :   uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
     112       12202 :   return Size + getCStringLength(Data.drop_front(Size));
     113             : }
     114             : 
     115         315 : 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         315 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     123         315 :   uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
     124         630 :   return Size + getCStringLength(Data.drop_front(Size));
     125             : }
     126             : 
     127          62 : 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          62 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     134          62 :   return 8 + getCStringLength(Data.drop_front(8));
     135             : }
     136             : 
     137         107 : 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         107 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     147             : 
     148             :   uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
     149         107 :   if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
     150             :     Size += 4;
     151             : 
     152         214 :   return Size + getCStringLength(Data.drop_front(Size));
     153             : }
     154             : 
     155          71 : 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          71 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     162          71 :   return 8 + getCStringLength(Data.drop_front(8));
     163             : }
     164             : 
     165           8 : 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           8 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     172           8 :   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          36 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     188          18 :   return Size;
     189             : }
     190             : 
     191             : 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             :   return 8;
     198             : }
     199             : 
     200             : 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             :   return 8;
     207             : }
     208             : 
     209         260 : static void handleFieldList(ArrayRef<uint8_t> Content,
     210             :                             SmallVectorImpl<TiReference> &Refs) {
     211             :   uint32_t Offset = 0;
     212             :   uint32_t ThisLen = 0;
     213        6993 :   while (!Content.empty()) {
     214             :     TypeLeafKind Kind =
     215             :         static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
     216        6733 :     switch (Kind) {
     217          25 :     case LF_BCLASS:
     218          25 :       ThisLen = handleBaseClass(Content, Offset, Refs);
     219          25 :       break;
     220        6101 :     case LF_ENUMERATE:
     221        6101 :       ThisLen = handleEnumerator(Content, Offset, Refs);
     222        6101 :       break;
     223         315 :     case LF_MEMBER:
     224         315 :       ThisLen = handleDataMember(Content, Offset, Refs);
     225         315 :       break;
     226          62 :     case LF_METHOD:
     227          62 :       ThisLen = handleOverloadedMethod(Content, Offset, Refs);
     228          62 :       break;
     229         107 :     case LF_ONEMETHOD:
     230         107 :       ThisLen = handleOneMethod(Content, Offset, Refs);
     231         107 :       break;
     232          71 :     case LF_NESTTYPE:
     233          71 :       ThisLen = handleNestedType(Content, Offset, Refs);
     234          71 :       break;
     235           8 :     case LF_STMEMBER:
     236           8 :       ThisLen = handleStaticDataMember(Content, Offset, Refs);
     237           8 :       break;
     238          18 :     case LF_VBCLASS:
     239             :     case LF_IVBCLASS:
     240          18 :       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        6733 :     Content = Content.drop_front(ThisLen);
     253        6733 :     Offset += ThisLen;
     254        6733 :     if (!Content.empty()) {
     255        6636 :       uint8_t Pad = Content.front();
     256        6636 :       if (Pad >= LF_PAD0) {
     257        1714 :         uint32_t Skip = Pad & 0x0F;
     258        1714 :         Content = Content.drop_front(Skip);
     259        1714 :         Offset += Skip;
     260             :       }
     261             :     }
     262             :   }
     263             : }
     264             : 
     265         357 : static void handlePointer(ArrayRef<uint8_t> Content,
     266             :                           SmallVectorImpl<TiReference> &Refs) {
     267         357 :   Refs.push_back({TiRefKind::TypeRef, 0, 1});
     268             : 
     269             :   uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
     270         357 :   if (isMemberPointer(Attrs))
     271          18 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     272         357 : }
     273             : 
     274        3191 : 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        3191 :   switch (Kind) {
     281         310 :   case TypeLeafKind::LF_FUNC_ID:
     282         310 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     283         310 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     284         310 :     break;
     285          75 :   case TypeLeafKind::LF_MFUNC_ID:
     286          75 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     287          75 :     break;
     288         344 :   case TypeLeafKind::LF_STRING_ID:
     289         344 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     290         344 :     break;
     291          37 :   case TypeLeafKind::LF_SUBSTR_LIST:
     292             :     Count = support::endian::read32le(Content.data());
     293          37 :     if (Count > 0)
     294          37 :       Refs.push_back({TiRefKind::IndexRef, 4, Count});
     295             :     break;
     296          38 :   case TypeLeafKind::LF_BUILDINFO:
     297          38 :     Count = support::endian::read16le(Content.data());
     298          38 :     if (Count > 0)
     299          38 :       Refs.push_back({TiRefKind::IndexRef, 2, Count});
     300             :     break;
     301         229 :   case TypeLeafKind::LF_UDT_SRC_LINE:
     302         229 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     303         229 :     Refs.push_back({TiRefKind::IndexRef, 4, 1});
     304         229 :     break;
     305           2 :   case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
     306           2 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     307           2 :     break;
     308          57 :   case TypeLeafKind::LF_MODIFIER:
     309          57 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     310          57 :     break;
     311         229 :   case TypeLeafKind::LF_PROCEDURE:
     312         229 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     313         229 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     314         229 :     break;
     315         274 :   case TypeLeafKind::LF_MFUNCTION:
     316         274 :     Refs.push_back({TiRefKind::TypeRef, 0, 3});
     317         274 :     Refs.push_back({TiRefKind::TypeRef, 16, 1});
     318         274 :     break;
     319         417 :   case TypeLeafKind::LF_ARGLIST:
     320             :     Count = support::endian::read32le(Content.data());
     321         417 :     if (Count > 0)
     322         215 :       Refs.push_back({TiRefKind::TypeRef, 4, Count});
     323             :     break;
     324          25 :   case TypeLeafKind::LF_ARRAY:
     325          25 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     326          25 :     break;
     327         350 :   case TypeLeafKind::LF_CLASS:
     328             :   case TypeLeafKind::LF_STRUCTURE:
     329             :   case TypeLeafKind::LF_INTERFACE:
     330         350 :     Refs.push_back({TiRefKind::TypeRef, 4, 3});
     331         350 :     break;
     332          15 :   case TypeLeafKind::LF_UNION:
     333          15 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     334          15 :     break;
     335          65 :   case TypeLeafKind::LF_ENUM:
     336          65 :     Refs.push_back({TiRefKind::TypeRef, 4, 2});
     337          65 :     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          62 :   case TypeLeafKind::LF_METHODLIST:
     347          62 :     handleMethodOverloadList(Content, Refs);
     348          62 :     break;
     349         260 :   case TypeLeafKind::LF_FIELDLIST:
     350         260 :     handleFieldList(Content, Refs);
     351         260 :     break;
     352         357 :   case TypeLeafKind::LF_POINTER:
     353         357 :     handlePointer(Content, Refs);
     354         357 :     break;
     355             :   default:
     356             :     break;
     357             :   }
     358        3191 : }
     359             : 
     360         575 : 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         575 :   switch (Kind) {
     367         124 :   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         124 :     Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
     374         124 :     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          32 :   case SymbolKind::S_BUILDINFO:
     383          32 :     Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
     384          32 :     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          33 :   case SymbolKind::S_LOCAL:
     393          33 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     394          33 :     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 refernces.
     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             :     break;
     443             :   // Scope ending symbols.
     444             :   case SymbolKind::S_END:
     445             :   case SymbolKind::S_INLINESITE_END:
     446             :   case SymbolKind::S_PROC_ID_END:
     447             :     break;
     448             :   default:
     449             :     return false; // Unknown symbol.
     450             :   }
     451             :   return true;
     452             : }
     453             : 
     454           0 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     455             :                                          SmallVectorImpl<TiReference> &Refs) {
     456           0 :   ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
     457           0 : }
     458             : 
     459         205 : static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
     460             :                                        ArrayRef<TiReference> Refs,
     461             :                                        SmallVectorImpl<TypeIndex> &Indices) {
     462             :   Indices.clear();
     463             : 
     464         205 :   if (Refs.empty())
     465           6 :     return;
     466             : 
     467             :   RecordData = RecordData.drop_front(sizeof(RecordPrefix));
     468             : 
     469         199 :   BinaryStreamReader Reader(RecordData, support::little);
     470         871 :   for (const auto &Ref : Refs) {
     471         336 :     Reader.setOffset(Ref.Offset);
     472             :     FixedStreamArray<TypeIndex> Run;
     473         672 :     cantFail(Reader.readArray(Run, Ref.Count));
     474        1344 :     Indices.append(Run.begin(), Run.end());
     475             :   }
     476             : }
     477             : 
     478         205 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     479             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     480         205 :   return discoverTypeIndices(Type.RecordData, Indices);
     481             : }
     482             : 
     483         205 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     484             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     485             :   SmallVector<TiReference, 4> Refs;
     486         205 :   discoverTypeIndices(RecordData, Refs);
     487         205 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     488         205 : }
     489             : 
     490        3191 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     491             :                                          SmallVectorImpl<TiReference> &Refs) {
     492             :   const RecordPrefix *P =
     493             :       reinterpret_cast<const RecordPrefix *>(RecordData.data());
     494             :   TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
     495        6382 :   ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
     496        3191 : }
     497             : 
     498         575 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     499             :     const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
     500         575 :   SymbolKind K = Sym.kind();
     501        1150 :   return ::discoverTypeIndices(Sym.content(), K, Refs);
     502             : }
     503             : 
     504           0 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     505             :     ArrayRef<uint8_t> RecordData, SmallVectorImpl<TiReference> &Refs) {
     506             :   const RecordPrefix *P =
     507             :       reinterpret_cast<const RecordPrefix *>(RecordData.data());
     508             :   SymbolKind K = static_cast<SymbolKind>(uint16_t(P->RecordKind));
     509           0 :   return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
     510           0 :                                Refs);
     511             : }
     512             : 
     513           0 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     514             :     ArrayRef<uint8_t> RecordData, SmallVectorImpl<TypeIndex> &Indices) {
     515             :   SmallVector<TiReference, 2> Refs;
     516           0 :   if (!discoverTypeIndicesInSymbol(RecordData, Refs))
     517             :     return false;
     518           0 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     519           0 :   return true;
     520             : }

Generated by: LCOV version 1.13