1 //===-- TypeRecord.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 10 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 11 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 12 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 13 14 using namespace llvm; 15 using namespace llvm::codeview; 16 17 //===----------------------------------------------------------------------===// 18 // Type record deserialization 19 //===----------------------------------------------------------------------===// 20 21 ErrorOr<MemberPointerInfo> 22 MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) { 23 const Layout *L = nullptr; 24 if (auto EC = consumeObject(Data, L)) 25 return EC; 26 27 TypeIndex T = L->ClassType; 28 uint16_t R = L->Representation; 29 PointerToMemberRepresentation PMR = 30 static_cast<PointerToMemberRepresentation>(R); 31 return MemberPointerInfo(T, PMR); 32 } 33 34 ErrorOr<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind, 35 ArrayRef<uint8_t> &Data) { 36 const Layout *L = nullptr; 37 if (auto EC = consumeObject(Data, L)) 38 return EC; 39 40 TypeIndex M = L->ModifiedType; 41 uint16_t O = L->Modifiers; 42 ModifierOptions MO = static_cast<ModifierOptions>(O); 43 return ModifierRecord(M, MO); 44 } 45 46 ErrorOr<ProcedureRecord> ProcedureRecord::deserialize(TypeRecordKind Kind, 47 ArrayRef<uint8_t> &Data) { 48 const Layout *L = nullptr; 49 if (auto EC = consumeObject(Data, L)) 50 return EC; 51 return ProcedureRecord(L->ReturnType, L->CallConv, L->Options, 52 L->NumParameters, L->ArgListType); 53 } 54 55 ErrorOr<MemberFunctionRecord> 56 MemberFunctionRecord::deserialize(TypeRecordKind Kind, 57 ArrayRef<uint8_t> &Data) { 58 const Layout *L = nullptr; 59 CV_DESERIALIZE(Data, L); 60 return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType, 61 L->CallConv, L->Options, L->NumParameters, 62 L->ArgListType, L->ThisAdjustment); 63 } 64 65 ErrorOr<MemberFuncIdRecord> 66 MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 67 const Layout *L = nullptr; 68 StringRef Name; 69 CV_DESERIALIZE(Data, L, Name); 70 return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name); 71 } 72 73 ErrorOr<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind, 74 ArrayRef<uint8_t> &Data) { 75 if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList) 76 return std::make_error_code(std::errc::illegal_byte_sequence); 77 78 const Layout *L = nullptr; 79 ArrayRef<TypeIndex> Indices; 80 CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs)); 81 return ArgListRecord(Kind, Indices); 82 } 83 84 ErrorOr<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind, 85 ArrayRef<uint8_t> &Data) { 86 const Layout *L = nullptr; 87 if (auto EC = consumeObject(Data, L)) 88 return EC; 89 90 PointerKind PtrKind = L->getPtrKind(); 91 PointerMode Mode = L->getPtrMode(); 92 uint32_t Opts = L->Attrs; 93 PointerOptions Options = static_cast<PointerOptions>(Opts); 94 uint8_t Size = L->getPtrSize(); 95 96 if (L->isPointerToMember()) { 97 auto E = MemberPointerInfo::deserialize(Data); 98 if (E.getError()) 99 return std::make_error_code(std::errc::illegal_byte_sequence); 100 return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E); 101 } 102 103 return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size); 104 } 105 106 ErrorOr<NestedTypeRecord> 107 NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 108 const Layout *L = nullptr; 109 StringRef Name; 110 CV_DESERIALIZE(Data, L, Name); 111 return NestedTypeRecord(L->Type, Name); 112 } 113 114 ErrorOr<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind, 115 ArrayRef<uint8_t> &Data) { 116 const Layout *L = nullptr; 117 uint64_t Size; 118 StringRef Name; 119 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name); 120 return ArrayRecord(L->ElementType, L->IndexType, Size, Name); 121 } 122 123 ErrorOr<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind, 124 ArrayRef<uint8_t> &Data) { 125 uint64_t Size = 0; 126 StringRef Name; 127 StringRef UniqueName; 128 uint16_t Props; 129 const Layout *L = nullptr; 130 131 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name, 132 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); 133 134 Props = L->Properties; 135 uint16_t WrtValue = (Props & WinRTKindMask) >> WinRTKindShift; 136 WindowsRTClassKind WRT = static_cast<WindowsRTClassKind>(WrtValue); 137 uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift; 138 HfaKind Hfa = static_cast<HfaKind>(HfaMask); 139 140 ClassOptions Options = static_cast<ClassOptions>(Props); 141 return ClassRecord(Kind, L->MemberCount, Options, Hfa, WRT, L->FieldList, 142 L->DerivedFrom, L->VShape, Size, Name, UniqueName); 143 } 144 145 ErrorOr<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind, 146 ArrayRef<uint8_t> &Data) { 147 uint64_t Size = 0; 148 StringRef Name; 149 StringRef UniqueName; 150 uint16_t Props; 151 152 const Layout *L = nullptr; 153 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name, 154 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); 155 156 Props = L->Properties; 157 158 uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift; 159 HfaKind Hfa = static_cast<HfaKind>(HfaMask); 160 ClassOptions Options = static_cast<ClassOptions>(Props); 161 return UnionRecord(L->MemberCount, Options, Hfa, L->FieldList, Size, Name, 162 UniqueName); 163 } 164 165 ErrorOr<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind, 166 ArrayRef<uint8_t> &Data) { 167 const Layout *L = nullptr; 168 StringRef Name; 169 StringRef UniqueName; 170 CV_DESERIALIZE(Data, L, Name, 171 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName())); 172 173 uint16_t P = L->Properties; 174 ClassOptions Options = static_cast<ClassOptions>(P); 175 return EnumRecord(L->NumEnumerators, Options, L->FieldListType, Name, 176 UniqueName, L->UnderlyingType); 177 } 178 179 ErrorOr<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind, 180 ArrayRef<uint8_t> &Data) { 181 const Layout *L = nullptr; 182 CV_DESERIALIZE(Data, L); 183 return BitFieldRecord(L->Type, L->BitSize, L->BitOffset); 184 } 185 186 ErrorOr<VFTableShapeRecord> 187 VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 188 const Layout *L = nullptr; 189 if (auto EC = consumeObject(Data, L)) 190 return EC; 191 192 std::vector<VFTableSlotKind> Slots; 193 uint16_t Count = L->VFEntryCount; 194 while (Count > 0) { 195 if (Data.empty()) 196 return std::make_error_code(std::errc::illegal_byte_sequence); 197 198 // Process up to 2 nibbles at a time (if there are at least 2 remaining) 199 uint8_t Value = Data[0] & 0x0F; 200 Slots.push_back(static_cast<VFTableSlotKind>(Value)); 201 if (--Count > 0) { 202 Value = (Data[0] & 0xF0) >> 4; 203 Slots.push_back(static_cast<VFTableSlotKind>(Value)); 204 --Count; 205 } 206 Data = Data.slice(1); 207 } 208 209 return VFTableShapeRecord(Slots); 210 } 211 212 ErrorOr<TypeServer2Record> 213 TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 214 const Layout *L = nullptr; 215 StringRef Name; 216 CV_DESERIALIZE(Data, L, Name); 217 return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name); 218 } 219 220 ErrorOr<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind, 221 ArrayRef<uint8_t> &Data) { 222 const Layout *L = nullptr; 223 StringRef Name; 224 CV_DESERIALIZE(Data, L, Name); 225 return StringIdRecord(L->id, Name); 226 } 227 228 ErrorOr<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind, 229 ArrayRef<uint8_t> &Data) { 230 const Layout *L = nullptr; 231 StringRef Name; 232 CV_DESERIALIZE(Data, L, Name); 233 return FuncIdRecord(L->ParentScope, L->FunctionType, Name); 234 } 235 236 ErrorOr<UdtSourceLineRecord> 237 UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 238 const Layout *L = nullptr; 239 CV_DESERIALIZE(Data, L); 240 return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber); 241 } 242 243 ErrorOr<BuildInfoRecord> BuildInfoRecord::deserialize(TypeRecordKind Kind, 244 ArrayRef<uint8_t> &Data) { 245 const Layout *L = nullptr; 246 ArrayRef<TypeIndex> Indices; 247 CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs)); 248 return BuildInfoRecord(Indices); 249 } 250 251 ErrorOr<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind, 252 ArrayRef<uint8_t> &Data) { 253 const Layout *L = nullptr; 254 StringRef Name; 255 std::vector<StringRef> Names; 256 CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names)); 257 return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset, 258 Name, Names); 259 } 260 261 ErrorOr<OneMethodRecord> OneMethodRecord::deserialize(TypeRecordKind Kind, 262 ArrayRef<uint8_t> &Data) { 263 const Layout *L = nullptr; 264 StringRef Name; 265 int32_t VFTableOffset = -1; 266 267 CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset, 268 L->Attrs.isIntroducedVirtual()), 269 Name); 270 271 MethodOptions Options = L->Attrs.getFlags(); 272 MethodKind MethKind = L->Attrs.getMethodKind(); 273 MemberAccess Access = L->Attrs.getAccess(); 274 OneMethodRecord Method(L->Type, MethKind, Options, Access, VFTableOffset, 275 Name); 276 // Validate the vftable offset. 277 if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0) 278 return std::make_error_code(std::errc::illegal_byte_sequence); 279 return Method; 280 } 281 282 ErrorOr<MethodOverloadListRecord> 283 MethodOverloadListRecord::deserialize(TypeRecordKind Kind, 284 ArrayRef<uint8_t> &Data) { 285 std::vector<OneMethodRecord> Methods; 286 while (!Data.empty()) { 287 const Layout *L = nullptr; 288 int32_t VFTableOffset = -1; 289 CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD( 290 VFTableOffset, L->Attrs.isIntroducedVirtual())); 291 292 MethodOptions Options = L->Attrs.getFlags(); 293 MethodKind MethKind = L->Attrs.getMethodKind(); 294 MemberAccess Access = L->Attrs.getAccess(); 295 296 Methods.emplace_back(L->Type, MethKind, Options, Access, VFTableOffset, 297 StringRef()); 298 299 // Validate the vftable offset. 300 auto &Method = Methods.back(); 301 if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0) 302 return std::make_error_code(std::errc::illegal_byte_sequence); 303 } 304 return MethodOverloadListRecord(Methods); 305 } 306 307 ErrorOr<OverloadedMethodRecord> 308 OverloadedMethodRecord::deserialize(TypeRecordKind Kind, 309 ArrayRef<uint8_t> &Data) { 310 const Layout *L = nullptr; 311 StringRef Name; 312 CV_DESERIALIZE(Data, L, Name); 313 return OverloadedMethodRecord(L->MethodCount, L->MethList, Name); 314 } 315 316 ErrorOr<DataMemberRecord> 317 DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 318 const Layout *L = nullptr; 319 uint64_t Offset; 320 StringRef Name; 321 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name); 322 return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name); 323 } 324 325 ErrorOr<StaticDataMemberRecord> 326 StaticDataMemberRecord::deserialize(TypeRecordKind Kind, 327 ArrayRef<uint8_t> &Data) { 328 const Layout *L = nullptr; 329 StringRef Name; 330 CV_DESERIALIZE(Data, L, Name); 331 return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name); 332 } 333 334 ErrorOr<EnumeratorRecord> 335 EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) { 336 const Layout *L = nullptr; 337 APSInt Value; 338 StringRef Name; 339 CV_DESERIALIZE(Data, L, Value, Name); 340 return EnumeratorRecord(L->Attrs.getAccess(), Value, Name); 341 } 342 343 ErrorOr<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind, 344 ArrayRef<uint8_t> &Data) { 345 const Layout *L = nullptr; 346 if (auto EC = consumeObject(Data, L)) 347 return EC; 348 return VFPtrRecord(L->Type); 349 } 350 351 ErrorOr<BaseClassRecord> BaseClassRecord::deserialize(TypeRecordKind Kind, 352 ArrayRef<uint8_t> &Data) { 353 const Layout *L = nullptr; 354 uint64_t Offset; 355 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset)); 356 return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset); 357 } 358 359 ErrorOr<VirtualBaseClassRecord> 360 VirtualBaseClassRecord::deserialize(TypeRecordKind Kind, 361 ArrayRef<uint8_t> &Data) { 362 const Layout *L = nullptr; 363 uint64_t Offset; 364 uint64_t Index; 365 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index)); 366 return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType, 367 Offset, Index); 368 } 369 370 ErrorOr<ListContinuationRecord> 371 ListContinuationRecord::deserialize(TypeRecordKind Kind, 372 ArrayRef<uint8_t> &Data) { 373 const Layout *L = nullptr; 374 CV_DESERIALIZE(Data, L); 375 return ListContinuationRecord(L->ContinuationIndex); 376 } 377 378 //===----------------------------------------------------------------------===// 379 // Type index remapping 380 //===----------------------------------------------------------------------===// 381 382 static bool remapIndex(ArrayRef<TypeIndex> IndexMap, TypeIndex &Idx) { 383 // Simple types are unchanged. 384 if (Idx.isSimple()) 385 return true; 386 unsigned MapPos = Idx.getIndex() - TypeIndex::FirstNonSimpleIndex; 387 if (MapPos < IndexMap.size()) { 388 Idx = IndexMap[MapPos]; 389 return true; 390 } 391 392 // This type index is invalid. Remap this to "not translated by cvpack", 393 // and return failure. 394 Idx = TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct); 395 return false; 396 } 397 398 bool ModifierRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 399 return remapIndex(IndexMap, ModifiedType); 400 } 401 402 bool ProcedureRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 403 bool Success = true; 404 Success &= remapIndex(IndexMap, ReturnType); 405 Success &= remapIndex(IndexMap, ArgumentList); 406 return Success; 407 } 408 409 bool MemberFunctionRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 410 bool Success = true; 411 Success &= remapIndex(IndexMap, ReturnType); 412 Success &= remapIndex(IndexMap, ClassType); 413 Success &= remapIndex(IndexMap, ThisType); 414 Success &= remapIndex(IndexMap, ArgumentList); 415 return Success; 416 } 417 418 bool MemberFuncIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 419 bool Success = true; 420 Success &= remapIndex(IndexMap, ClassType); 421 Success &= remapIndex(IndexMap, FunctionType); 422 return Success; 423 } 424 425 bool ArgListRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 426 bool Success = true; 427 for (TypeIndex &Str : StringIndices) 428 Success &= remapIndex(IndexMap, Str); 429 return Success; 430 } 431 432 bool MemberPointerInfo::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 433 return remapIndex(IndexMap, ContainingType); 434 } 435 436 bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 437 bool Success = true; 438 Success &= remapIndex(IndexMap, ReferentType); 439 if (isPointerToMember()) 440 Success &= MemberInfo.remapTypeIndices(IndexMap); 441 return Success; 442 } 443 444 bool NestedTypeRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 445 return remapIndex(IndexMap, Type); 446 } 447 448 bool ArrayRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 449 bool Success = true; 450 Success &= remapIndex(IndexMap, ElementType); 451 Success &= remapIndex(IndexMap, IndexType); 452 return Success; 453 } 454 455 bool TagRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 456 return remapIndex(IndexMap, FieldList); 457 } 458 459 bool ClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 460 bool Success = true; 461 Success &= TagRecord::remapTypeIndices(IndexMap); 462 Success &= remapIndex(IndexMap, DerivationList); 463 Success &= remapIndex(IndexMap, VTableShape); 464 return Success; 465 } 466 467 bool EnumRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 468 bool Success = true; 469 Success &= TagRecord::remapTypeIndices(IndexMap); 470 Success &= remapIndex(IndexMap, UnderlyingType); 471 return Success; 472 } 473 474 bool BitFieldRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 475 return remapIndex(IndexMap, Type); 476 } 477 478 bool VFTableShapeRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 479 return true; 480 } 481 482 bool TypeServer2Record::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 483 return true; 484 } 485 486 bool StringIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 487 return remapIndex(IndexMap, Id); 488 } 489 490 bool FuncIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 491 bool Success = true; 492 Success &= remapIndex(IndexMap, ParentScope); 493 Success &= remapIndex(IndexMap, FunctionType); 494 return Success; 495 } 496 497 bool UdtSourceLineRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 498 bool Success = true; 499 Success &= remapIndex(IndexMap, UDT); 500 Success &= remapIndex(IndexMap, SourceFile); 501 return Success; 502 } 503 504 bool UdtModSourceLineRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 505 bool Success = true; 506 Success &= remapIndex(IndexMap, UDT); 507 Success &= remapIndex(IndexMap, SourceFile); 508 return Success; 509 } 510 511 bool BuildInfoRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 512 bool Success = true; 513 for (TypeIndex &Arg : ArgIndices) 514 Success &= remapIndex(IndexMap, Arg); 515 return Success; 516 } 517 518 bool VFTableRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 519 bool Success = true; 520 Success &= remapIndex(IndexMap, CompleteClass); 521 Success &= remapIndex(IndexMap, OverriddenVFTable); 522 return Success; 523 } 524 525 bool OneMethodRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 526 bool Success = true; 527 Success &= remapIndex(IndexMap, Type); 528 return Success; 529 } 530 531 bool MethodOverloadListRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 532 bool Success = true; 533 for (OneMethodRecord &Meth : Methods) 534 if ((Success = Meth.remapTypeIndices(IndexMap))) 535 return Success; 536 return Success; 537 } 538 539 bool OverloadedMethodRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 540 return remapIndex(IndexMap, MethodList); 541 } 542 543 bool DataMemberRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 544 return remapIndex(IndexMap, Type); 545 } 546 547 bool StaticDataMemberRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 548 return remapIndex(IndexMap, Type); 549 } 550 551 bool EnumeratorRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 552 return true; 553 } 554 555 bool VFPtrRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 556 return remapIndex(IndexMap, Type); 557 } 558 559 bool BaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 560 return remapIndex(IndexMap, Type); 561 } 562 563 bool VirtualBaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 564 bool Success = true; 565 Success &= remapIndex(IndexMap, BaseType); 566 Success &= remapIndex(IndexMap, VBPtrType); 567 return Success; 568 } 569 570 bool ListContinuationRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { 571 return remapIndex(IndexMap, ContinuationIndex); 572 } 573