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-02-23 15:42:53 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         260 :   Attrs &= uint16_t(MethodOptions::MethodKindMask);
      19         260 :   Attrs >>= 2;
      20         260 :   return MethodKind(Attrs);
      21             : }
      22             : 
      23             : static inline bool isIntroVirtual(uint16_t Attrs) {
      24             :   MethodKind MK = getMethodKind(Attrs);
      25         260 :   return MK == MethodKind::IntroducingVirtual ||
      26         260 :          MK == MethodKind::PureIntroducingVirtual;
      27             : }
      28             : 
      29             : static inline PointerMode getPointerMode(uint32_t Attrs) {
      30         325 :   return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
      31         325 :                                   PointerRecord::PointerModeMask);
      32             : }
      33             : 
      34             : static inline bool isMemberPointer(uint32_t Attrs) {
      35             :   PointerMode Mode = getPointerMode(Attrs);
      36         325 :   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        6428 :   if (N < LF_NUMERIC)
      43             :     return 2;
      44             : 
      45             :   assert(N <= LF_UQUADWORD);
      46             : 
      47           8 :   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           8 :   return 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        6629 :   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         389 :   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          23 : 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          23 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     102          23 :   return 8 + getEncodedIntegerLength(Data.drop_front(8));
     103             : }
     104             : 
     105        6053 : 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        6053 :   uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
     112       12106 :   return Size + getCStringLength(Data.drop_front(Size));
     113             : }
     114             : 
     115         324 : 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         324 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     123         324 :   uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
     124         648 :   return Size + getCStringLength(Data.drop_front(Size));
     125             : }
     126             : 
     127          67 : 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          67 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     134          67 :   return 8 + getCStringLength(Data.drop_front(8));
     135             : }
     136             : 
     137          99 : 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          99 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     147             : 
     148             :   uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
     149          99 :   if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
     150             :     Size += 4;
     151             : 
     152         198 :   return Size + getCStringLength(Data.drop_front(Size));
     153             : }
     154             : 
     155          78 : 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          78 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     162          78 :   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          14 : 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          14 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 2});
     186          14 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     187          28 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     188          14 :   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          15 :   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         259 : static void handleFieldList(ArrayRef<uint8_t> Content,
     210             :                             SmallVectorImpl<TiReference> &Refs) {
     211             :   uint32_t Offset = 0;
     212             :   uint32_t ThisLen = 0;
     213        6946 :   while (!Content.empty()) {
     214             :     TypeLeafKind Kind =
     215             :         static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
     216        6695 :     switch (Kind) {
     217          23 :     case LF_BCLASS:
     218          23 :       ThisLen = handleBaseClass(Content, Offset, Refs);
     219          23 :       break;
     220        6053 :     case LF_ENUMERATE:
     221        6053 :       ThisLen = handleEnumerator(Content, Offset, Refs);
     222        6053 :       break;
     223         324 :     case LF_MEMBER:
     224         324 :       ThisLen = handleDataMember(Content, Offset, Refs);
     225         324 :       break;
     226          67 :     case LF_METHOD:
     227          67 :       ThisLen = handleOverloadedMethod(Content, Offset, Refs);
     228          67 :       break;
     229          99 :     case LF_ONEMETHOD:
     230          99 :       ThisLen = handleOneMethod(Content, Offset, Refs);
     231          99 :       break;
     232          78 :     case LF_NESTTYPE:
     233          78 :       ThisLen = handleNestedType(Content, Offset, Refs);
     234          78 :       break;
     235           8 :     case LF_STMEMBER:
     236           8 :       ThisLen = handleStaticDataMember(Content, Offset, Refs);
     237           8 :       break;
     238          14 :     case LF_VBCLASS:
     239             :     case LF_IVBCLASS:
     240          14 :       ThisLen =
     241          14 :           handleVirtualBaseClass(Content, Offset, Kind == LF_VBCLASS, Refs);
     242          14 :       break;
     243             :     case LF_VFUNCTAB:
     244             :       ThisLen = handleVFPtr(Content, Offset, Refs);
     245          15 :       break;
     246             :     case LF_INDEX:
     247             :       ThisLen = handleListContinuation(Content, Offset, Refs);
     248           6 :       break;
     249             :     default:
     250             :       return;
     251             :     }
     252        6687 :     Content = Content.drop_front(ThisLen);
     253        6687 :     Offset += ThisLen;
     254        6687 :     if (!Content.empty()) {
     255        6588 :       uint8_t Pad = Content.front();
     256        6588 :       if (Pad >= LF_PAD0) {
     257        1678 :         uint32_t Skip = Pad & 0x0F;
     258        1678 :         Content = Content.drop_front(Skip);
     259        1678 :         Offset += Skip;
     260             :       }
     261             :     }
     262             :   }
     263             : }
     264             : 
     265         325 : static void handlePointer(ArrayRef<uint8_t> Content,
     266             :                           SmallVectorImpl<TiReference> &Refs) {
     267         325 :   Refs.push_back({TiRefKind::TypeRef, 0, 1});
     268             : 
     269             :   uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
     270         325 :   if (isMemberPointer(Attrs))
     271          14 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     272         325 : }
     273             : 
     274        3056 : 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        3056 :   switch (Kind) {
     281         294 :   case TypeLeafKind::LF_FUNC_ID:
     282         294 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     283         294 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     284         294 :     break;
     285          59 :   case TypeLeafKind::LF_MFUNC_ID:
     286          59 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     287          59 :     break;
     288         333 :   case TypeLeafKind::LF_STRING_ID:
     289         333 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     290         333 :     break;
     291          38 :   case TypeLeafKind::LF_SUBSTR_LIST:
     292             :     Count = support::endian::read32le(Content.data());
     293          38 :     if (Count > 0)
     294          38 :       Refs.push_back({TiRefKind::IndexRef, 4, Count});
     295             :     break;
     296          39 :   case TypeLeafKind::LF_BUILDINFO:
     297          39 :     Count = support::endian::read16le(Content.data());
     298          39 :     if (Count > 0)
     299          39 :       Refs.push_back({TiRefKind::IndexRef, 2, Count});
     300             :     break;
     301         225 :   case TypeLeafKind::LF_UDT_SRC_LINE:
     302         225 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     303         225 :     Refs.push_back({TiRefKind::IndexRef, 4, 1});
     304         225 :     break;
     305           2 :   case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
     306           2 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     307           2 :     break;
     308          51 :   case TypeLeafKind::LF_MODIFIER:
     309          51 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     310          51 :     break;
     311         215 :   case TypeLeafKind::LF_PROCEDURE:
     312         215 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     313         215 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     314         215 :     break;
     315         269 :   case TypeLeafKind::LF_MFUNCTION:
     316         269 :     Refs.push_back({TiRefKind::TypeRef, 0, 3});
     317         269 :     Refs.push_back({TiRefKind::TypeRef, 16, 1});
     318         269 :     break;
     319         393 :   case TypeLeafKind::LF_ARGLIST:
     320             :     Count = support::endian::read32le(Content.data());
     321         393 :     if (Count > 0)
     322         214 :       Refs.push_back({TiRefKind::TypeRef, 4, Count});
     323             :     break;
     324          24 :   case TypeLeafKind::LF_ARRAY:
     325          24 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     326          24 :     break;
     327         340 :   case TypeLeafKind::LF_CLASS:
     328             :   case TypeLeafKind::LF_STRUCTURE:
     329             :   case TypeLeafKind::LF_INTERFACE:
     330         340 :     Refs.push_back({TiRefKind::TypeRef, 4, 3});
     331         340 :     break;
     332          12 :   case TypeLeafKind::LF_UNION:
     333          12 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     334          12 :     break;
     335          73 :   case TypeLeafKind::LF_ENUM:
     336          73 :     Refs.push_back({TiRefKind::TypeRef, 4, 2});
     337          73 :     break;
     338          12 :   case TypeLeafKind::LF_BITFIELD:
     339          12 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     340          12 :     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         259 :   case TypeLeafKind::LF_FIELDLIST:
     350         259 :     handleFieldList(Content, Refs);
     351         259 :     break;
     352         325 :   case TypeLeafKind::LF_POINTER:
     353         325 :     handlePointer(Content, Refs);
     354         325 :     break;
     355             :   default:
     356             :     break;
     357             :   }
     358        3056 : }
     359             : 
     360         574 : 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         574 :   switch (Kind) {
     367         120 :   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         120 :     Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
     374         120 :     break;
     375         109 :   case SymbolKind::S_UDT:
     376         109 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
     377         109 :     break;
     378          21 :   case SymbolKind::S_GDATA32:
     379             :   case SymbolKind::S_LDATA32:
     380          21 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     381          21 :     break;
     382          33 :   case SymbolKind::S_BUILDINFO:
     383          33 :     Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
     384          33 :     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          27 :   case SymbolKind::S_LOCAL:
     393          27 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     394          27 :     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         203 : static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
     460             :                                        ArrayRef<TiReference> Refs,
     461             :                                        SmallVectorImpl<TypeIndex> &Indices) {
     462             :   Indices.clear();
     463             : 
     464         203 :   if (Refs.empty())
     465           6 :     return;
     466             : 
     467             :   RecordData = RecordData.drop_front(sizeof(RecordPrefix));
     468             : 
     469         197 :   BinaryStreamReader Reader(RecordData, support::little);
     470         861 :   for (const auto &Ref : Refs) {
     471         332 :     Reader.setOffset(Ref.Offset);
     472             :     FixedStreamArray<TypeIndex> Run;
     473         664 :     cantFail(Reader.readArray(Run, Ref.Count));
     474        1328 :     Indices.append(Run.begin(), Run.end());
     475             :   }
     476             : }
     477             : 
     478         203 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     479             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     480         203 :   return discoverTypeIndices(Type.RecordData, Indices);
     481             : }
     482             : 
     483         203 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     484             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     485             :   SmallVector<TiReference, 4> Refs;
     486         203 :   discoverTypeIndices(RecordData, Refs);
     487         203 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     488         203 : }
     489             : 
     490        3056 : 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        6112 :   ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
     496        3056 : }
     497             : 
     498         574 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     499             :     const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
     500         574 :   SymbolKind K = Sym.kind();
     501        1148 :   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