LCOV - code coverage report
Current view: top level - lib/DebugInfo/CodeView - TypeIndexDiscovery.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 230 261 88.1 %
Date: 2017-09-14 15:23:50 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         130 :   Attrs &= uint16_t(MethodOptions::MethodKindMask);
      19         130 :   Attrs >>= 2;
      20         130 :   return MethodKind(Attrs);
      21             : }
      22             : 
      23             : static inline bool isIntroVirtual(uint16_t Attrs) {
      24         130 :   MethodKind MK = getMethodKind(Attrs);
      25         130 :   return MK == MethodKind::IntroducingVirtual ||
      26         130 :          MK == MethodKind::PureIntroducingVirtual;
      27             : }
      28             : 
      29             : static inline PointerMode getPointerMode(uint32_t Attrs) {
      30         139 :   return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
      31         139 :                                   PointerRecord::PointerModeMask);
      32             : }
      33             : 
      34             : static inline bool isMemberPointer(uint32_t Attrs) {
      35         139 :   PointerMode Mode = getPointerMode(Attrs);
      36         139 :   return Mode == PointerMode::PointerToDataMember ||
      37             :          Mode == PointerMode::PointerToMemberFunction;
      38             : }
      39             : 
      40             : static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
      41         684 :   uint16_t N = support::endian::read16le(Data.data());
      42         342 :   if (N < LF_NUMERIC)
      43             :     return 2;
      44             : 
      45             :   assert(N <= LF_UQUADWORD);
      46             : 
      47           4 :   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           4 :   return Sizes[N - LF_NUMERIC];
      62             : }
      63             : 
      64             : static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) {
      65         431 :   const char *S = reinterpret_cast<const char *>(Data.data());
      66         431 :   return strlen(S) + 1;
      67             : }
      68             : 
      69          40 : static void handleMethodOverloadList(ArrayRef<uint8_t> Content,
      70             :                                      SmallVectorImpl<TiReference> &Refs) {
      71          40 :   uint32_t Offset = 0;
      72             : 
      73         232 :   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          96 :     uint32_t Len = 8;
      84             : 
      85         192 :     uint16_t Attrs = support::endian::read16le(Content.data());
      86          96 :     Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
      87             : 
      88          96 :     if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
      89           4 :       Len += 4;
      90          96 :     Offset += Len;
      91         192 :     Content = Content.drop_front(Len);
      92             :   }
      93          40 : }
      94             : 
      95           9 : 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           9 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     102          18 :   return 8 + getEncodedIntegerLength(Data.drop_front(8));
     103             : }
     104             : 
     105         182 : 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         364 :   uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
     112         546 :   return Size + getCStringLength(Data.drop_front(Size));
     113             : }
     114             : 
     115         133 : 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         133 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     123         266 :   uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
     124         399 :   return Size + getCStringLength(Data.drop_front(Size));
     125             : }
     126             : 
     127          40 : 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          40 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     134          80 :   return 8 + getCStringLength(Data.drop_front(8));
     135             : }
     136             : 
     137          34 : 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          34 :   uint32_t Size = 8;
     146          34 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     147             : 
     148          68 :   uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
     149          34 :   if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
     150          10 :     Size += 4;
     151             : 
     152         102 :   return Size + getCStringLength(Data.drop_front(Size));
     153             : }
     154             : 
     155          37 : 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          37 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     162          74 :   return 8 + getCStringLength(Data.drop_front(8));
     163             : }
     164             : 
     165           5 : 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           5 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     172          10 :   return 8 + getCStringLength(Data.drop_front(8));
     173             : }
     174             : 
     175           9 : 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           9 :   uint32_t Size = 12;
     185           9 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 2});
     186          27 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     187          27 :   Size += getEncodedIntegerLength(Data.drop_front(Size));
     188           9 :   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           5 :   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           2 :   Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
     206             :   return 8;
     207             : }
     208             : 
     209         105 : static void handleFieldList(ArrayRef<uint8_t> Content,
     210             :                             SmallVectorImpl<TiReference> &Refs) {
     211         105 :   uint32_t Offset = 0;
     212         105 :   uint32_t ThisLen = 0;
     213         561 :   while (!Content.empty()) {
     214             :     TypeLeafKind Kind =
     215         920 :         static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
     216         460 :     switch (Kind) {
     217           9 :     case LF_BCLASS:
     218           9 :       ThisLen = handleBaseClass(Content, Offset, Refs);
     219           9 :       break;
     220         182 :     case LF_ENUMERATE:
     221         182 :       ThisLen = handleEnumerator(Content, Offset, Refs);
     222         182 :       break;
     223         133 :     case LF_MEMBER:
     224         133 :       ThisLen = handleDataMember(Content, Offset, Refs);
     225         133 :       break;
     226          40 :     case LF_METHOD:
     227          40 :       ThisLen = handleOverloadedMethod(Content, Offset, Refs);
     228          40 :       break;
     229          34 :     case LF_ONEMETHOD:
     230          34 :       ThisLen = handleOneMethod(Content, Offset, Refs);
     231          34 :       break;
     232          37 :     case LF_NESTTYPE:
     233          37 :       ThisLen = handleNestedType(Content, Offset, Refs);
     234          37 :       break;
     235           5 :     case LF_STMEMBER:
     236           5 :       ThisLen = handleStaticDataMember(Content, Offset, Refs);
     237           5 :       break;
     238           9 :     case LF_VBCLASS:
     239             :     case LF_IVBCLASS:
     240           9 :       ThisLen =
     241           9 :           handleVirtualBaseClass(Content, Offset, Kind == LF_VBCLASS, Refs);
     242           9 :       break;
     243             :     case LF_VFUNCTAB:
     244          10 :       ThisLen = handleVFPtr(Content, Offset, Refs);
     245           5 :       break;
     246             :     case LF_INDEX:
     247           4 :       ThisLen = handleListContinuation(Content, Offset, Refs);
     248           2 :       break;
     249             :     default:
     250             :       return;
     251             :     }
     252         912 :     Content = Content.drop_front(ThisLen);
     253         456 :     Offset += ThisLen;
     254         456 :     if (!Content.empty()) {
     255         424 :       uint8_t Pad = Content.front();
     256         424 :       if (Pad >= LF_PAD0) {
     257         334 :         uint32_t Skip = Pad & 0x0F;
     258         668 :         Content = Content.drop_front(Skip);
     259         334 :         Offset += Skip;
     260             :       }
     261             :     }
     262             :   }
     263             : }
     264             : 
     265         139 : static void handlePointer(ArrayRef<uint8_t> Content,
     266             :                           SmallVectorImpl<TiReference> &Refs) {
     267         139 :   Refs.push_back({TiRefKind::TypeRef, 0, 1});
     268             : 
     269         278 :   uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
     270         139 :   if (isMemberPointer(Attrs))
     271           2 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     272         139 : }
     273             : 
     274        1252 : 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        1252 :   switch (Kind) {
     281          95 :   case TypeLeafKind::LF_FUNC_ID:
     282          95 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     283          95 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     284          95 :     break;
     285          14 :   case TypeLeafKind::LF_MFUNC_ID:
     286          14 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     287          14 :     break;
     288         207 :   case TypeLeafKind::LF_STRING_ID:
     289         207 :     Refs.push_back({TiRefKind::IndexRef, 0, 1});
     290         207 :     break;
     291          33 :   case TypeLeafKind::LF_SUBSTR_LIST:
     292          66 :     Count = support::endian::read32le(Content.data());
     293          33 :     if (Count > 0)
     294          33 :       Refs.push_back({TiRefKind::IndexRef, 4, Count});
     295             :     break;
     296          33 :   case TypeLeafKind::LF_BUILDINFO:
     297          66 :     Count = support::endian::read16le(Content.data());
     298          33 :     if (Count > 0)
     299          33 :       Refs.push_back({TiRefKind::IndexRef, 2, Count});
     300             :     break;
     301          80 :   case TypeLeafKind::LF_UDT_SRC_LINE:
     302          80 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     303          80 :     Refs.push_back({TiRefKind::IndexRef, 4, 1});
     304          80 :     break;
     305           2 :   case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
     306           2 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     307           2 :     break;
     308          21 :   case TypeLeafKind::LF_MODIFIER:
     309          21 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     310          21 :     break;
     311          63 :   case TypeLeafKind::LF_PROCEDURE:
     312          63 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     313          63 :     Refs.push_back({TiRefKind::TypeRef, 8, 1});
     314          63 :     break;
     315         118 :   case TypeLeafKind::LF_MFUNCTION:
     316         118 :     Refs.push_back({TiRefKind::TypeRef, 0, 3});
     317         118 :     Refs.push_back({TiRefKind::TypeRef, 16, 1});
     318         118 :     break;
     319         123 :   case TypeLeafKind::LF_ARGLIST:
     320         246 :     Count = support::endian::read32le(Content.data());
     321         123 :     if (Count > 0)
     322          95 :       Refs.push_back({TiRefKind::TypeRef, 4, Count});
     323             :     break;
     324           8 :   case TypeLeafKind::LF_ARRAY:
     325           8 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     326           8 :     break;
     327         111 :   case TypeLeafKind::LF_CLASS:
     328             :   case TypeLeafKind::LF_STRUCTURE:
     329             :   case TypeLeafKind::LF_INTERFACE:
     330         111 :     Refs.push_back({TiRefKind::TypeRef, 4, 3});
     331         111 :     break;
     332           6 :   case TypeLeafKind::LF_UNION:
     333           6 :     Refs.push_back({TiRefKind::TypeRef, 4, 1});
     334           6 :     break;
     335          37 :   case TypeLeafKind::LF_ENUM:
     336          37 :     Refs.push_back({TiRefKind::TypeRef, 4, 2});
     337          37 :     break;
     338           6 :   case TypeLeafKind::LF_BITFIELD:
     339           6 :     Refs.push_back({TiRefKind::TypeRef, 0, 1});
     340           6 :     break;
     341           4 :   case TypeLeafKind::LF_VFTABLE:
     342           4 :     Refs.push_back({TiRefKind::TypeRef, 0, 2});
     343           4 :     break;
     344             :   case TypeLeafKind::LF_VTSHAPE:
     345             :     break;
     346          40 :   case TypeLeafKind::LF_METHODLIST:
     347          40 :     handleMethodOverloadList(Content, Refs);
     348          40 :     break;
     349         105 :   case TypeLeafKind::LF_FIELDLIST:
     350         105 :     handleFieldList(Content, Refs);
     351         105 :     break;
     352         139 :   case TypeLeafKind::LF_POINTER:
     353         139 :     handlePointer(Content, Refs);
     354         139 :     break;
     355             :   default:
     356             :     break;
     357             :   }
     358        1252 : }
     359             : 
     360         309 : 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         309 :   switch (Kind) {
     367          76 :   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          76 :     Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
     374          76 :     break;
     375          36 :   case SymbolKind::S_UDT:
     376          36 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
     377          36 :     break;
     378          15 :   case SymbolKind::S_GDATA32:
     379             :   case SymbolKind::S_LDATA32:
     380          15 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     381          15 :     break;
     382          27 :   case SymbolKind::S_BUILDINFO:
     383          27 :     Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags
     384          27 :     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           0 :   case SymbolKind::S_FILESTATIC:
     390           0 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     391           0 :     break;
     392           5 :   case SymbolKind::S_LOCAL:
     393           5 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     394           5 :     break;
     395           0 :   case SymbolKind::S_CONSTANT:
     396           0 :     Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type
     397           0 :     break;
     398           9 :   case SymbolKind::S_BPREL32:
     399             :   case SymbolKind::S_REGREL32:
     400           9 :     Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type
     401           9 :     break;
     402           0 :   case SymbolKind::S_CALLSITEINFO:
     403           0 :     Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature
     404           0 :     break;
     405           2 :   case SymbolKind::S_CALLERS:
     406             :   case SymbolKind::S_CALLEES:
     407             :     // The record is a count followed by an array of type indices.
     408           4 :     Count = *reinterpret_cast<const ulittle32_t *>(Content.data());
     409           2 :     Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees
     410           2 :     break;
     411           0 :   case SymbolKind::S_INLINESITE:
     412           0 :     Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee
     413           0 :     break;
     414           0 :   case SymbolKind::S_HEAPALLOCSITE:
     415             :     // FIXME: It's not clear if this is a type or item reference.
     416           0 :     Refs.push_back({TiRefKind::IndexRef, 8, 1}); // signature
     417           0 :     break;
     418             : 
     419             :   // Defranges don't have types, just registers and code offsets.
     420             :   case SymbolKind::S_DEFRANGE_REGISTER:
     421             :   case SymbolKind::S_DEFRANGE_REGISTER_REL:
     422             :   case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
     423             :   case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
     424             :   case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
     425             :   case SymbolKind::S_DEFRANGE_SUBFIELD:
     426             :     break;
     427             : 
     428             :   // No type refernces.
     429             :   case SymbolKind::S_LABEL32:
     430             :   case SymbolKind::S_OBJNAME:
     431             :   case SymbolKind::S_COMPILE:
     432             :   case SymbolKind::S_COMPILE2:
     433             :   case SymbolKind::S_COMPILE3:
     434             :   case SymbolKind::S_ENVBLOCK:
     435             :   case SymbolKind::S_BLOCK32:
     436             :   case SymbolKind::S_FRAMEPROC:
     437             :     break;
     438             :   // Scope ending symbols.
     439             :   case SymbolKind::S_END:
     440             :   case SymbolKind::S_INLINESITE_END:
     441             :   case SymbolKind::S_PROC_ID_END:
     442             :     break;
     443             :   default:
     444             :     return false; // Unknown symbol.
     445             :   }
     446             :   return true;
     447             : }
     448             : 
     449           0 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     450             :                                          SmallVectorImpl<TiReference> &Refs) {
     451           0 :   ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
     452           0 : }
     453             : 
     454         181 : static void resolveTypeIndexReferences(ArrayRef<uint8_t> RecordData,
     455             :                                        ArrayRef<TiReference> Refs,
     456             :                                        SmallVectorImpl<TypeIndex> &Indices) {
     457         181 :   Indices.clear();
     458             : 
     459         181 :   if (Refs.empty())
     460           6 :     return;
     461             : 
     462         175 :   RecordData = RecordData.drop_front(sizeof(RecordPrefix));
     463             : 
     464         350 :   BinaryStreamReader Reader(RecordData, support::little);
     465         647 :   for (const auto &Ref : Refs) {
     466         594 :     Reader.setOffset(Ref.Offset);
     467         594 :     FixedStreamArray<TypeIndex> Run;
     468         891 :     cantFail(Reader.readArray(Run, Ref.Count));
     469        1188 :     Indices.append(Run.begin(), Run.end());
     470             :   }
     471             : }
     472             : 
     473         146 : void llvm::codeview::discoverTypeIndices(const CVType &Type,
     474             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     475         146 :   return discoverTypeIndices(Type.RecordData, Indices);
     476             : }
     477             : 
     478         181 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     479             :                                          SmallVectorImpl<TypeIndex> &Indices) {
     480         362 :   SmallVector<TiReference, 4> Refs;
     481         181 :   discoverTypeIndices(RecordData, Refs);
     482         181 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     483         181 : }
     484             : 
     485        1252 : void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
     486             :                                          SmallVectorImpl<TiReference> &Refs) {
     487             :   const RecordPrefix *P =
     488        1252 :       reinterpret_cast<const RecordPrefix *>(RecordData.data());
     489        2504 :   TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
     490        2504 :   ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
     491        1252 : }
     492             : 
     493         309 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     494             :     const CVSymbol &Sym, SmallVectorImpl<TiReference> &Refs) {
     495         309 :   SymbolKind K = Sym.kind();
     496         618 :   return ::discoverTypeIndices(Sym.content(), K, Refs);
     497             : }
     498             : 
     499           0 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     500             :     ArrayRef<uint8_t> RecordData, SmallVectorImpl<TiReference> &Refs) {
     501             :   const RecordPrefix *P =
     502           0 :       reinterpret_cast<const RecordPrefix *>(RecordData.data());
     503           0 :   SymbolKind K = static_cast<SymbolKind>(uint16_t(P->RecordKind));
     504           0 :   return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K,
     505           0 :                                Refs);
     506             : }
     507             : 
     508           0 : bool llvm::codeview::discoverTypeIndicesInSymbol(
     509             :     ArrayRef<uint8_t> RecordData, SmallVectorImpl<TypeIndex> &Indices) {
     510           0 :   SmallVector<TiReference, 2> Refs;
     511           0 :   if (!discoverTypeIndicesInSymbol(RecordData, Refs))
     512             :     return false;
     513           0 :   resolveTypeIndexReferences(RecordData, Refs, Indices);
     514           0 :   return true;
     515             : }

Generated by: LCOV version 1.13