1 //===-- TypeRecord.cpp ------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
11 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
12 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
15 using namespace llvm::codeview;
17 //===----------------------------------------------------------------------===//
18 // Type record deserialization
19 //===----------------------------------------------------------------------===//
21 ErrorOr<MemberPointerInfo>
22 MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
23 const Layout *L = nullptr;
24 if (auto EC = consumeObject(Data, L))
27 TypeIndex T = L->ClassType;
28 uint16_t R = L->Representation;
29 PointerToMemberRepresentation PMR =
30 static_cast<PointerToMemberRepresentation>(R);
31 return MemberPointerInfo(T, PMR);
34 ErrorOr<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
35 ArrayRef<uint8_t> &Data) {
36 const Layout *L = nullptr;
37 if (auto EC = consumeObject(Data, L))
40 TypeIndex M = L->ModifiedType;
41 uint16_t O = L->Modifiers;
42 ModifierOptions MO = static_cast<ModifierOptions>(O);
43 return ModifierRecord(M, MO);
46 ErrorOr<ProcedureRecord> ProcedureRecord::deserialize(TypeRecordKind Kind,
47 ArrayRef<uint8_t> &Data) {
48 const Layout *L = nullptr;
49 if (auto EC = consumeObject(Data, L))
51 return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
52 L->NumParameters, L->ArgListType);
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);
65 ErrorOr<MemberFuncIdRecord>
66 MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
67 const Layout *L = nullptr;
69 CV_DESERIALIZE(Data, L, Name);
70 return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
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);
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);
84 ErrorOr<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
85 ArrayRef<uint8_t> &Data) {
86 const Layout *L = nullptr;
87 if (auto EC = consumeObject(Data, L))
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();
96 if (L->isPointerToMember()) {
97 auto E = MemberPointerInfo::deserialize(Data);
99 return std::make_error_code(std::errc::illegal_byte_sequence);
100 return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E);
103 return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size);
106 ErrorOr<NestedTypeRecord>
107 NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
108 const Layout *L = nullptr;
110 CV_DESERIALIZE(Data, L, Name);
111 return NestedTypeRecord(L->Type, Name);
114 ErrorOr<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
115 ArrayRef<uint8_t> &Data) {
116 const Layout *L = nullptr;
119 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name);
120 return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
123 ErrorOr<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
124 ArrayRef<uint8_t> &Data) {
127 StringRef UniqueName;
129 const Layout *L = nullptr;
131 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
132 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
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);
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);
145 ErrorOr<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
146 ArrayRef<uint8_t> &Data) {
149 StringRef UniqueName;
152 const Layout *L = nullptr;
153 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
154 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
156 Props = L->Properties;
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,
165 ErrorOr<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
166 ArrayRef<uint8_t> &Data) {
167 const Layout *L = nullptr;
169 StringRef UniqueName;
170 CV_DESERIALIZE(Data, L, Name,
171 CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
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);
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);
186 ErrorOr<VFTableShapeRecord>
187 VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
188 const Layout *L = nullptr;
189 if (auto EC = consumeObject(Data, L))
192 std::vector<VFTableSlotKind> Slots;
193 uint16_t Count = L->VFEntryCount;
196 return std::make_error_code(std::errc::illegal_byte_sequence);
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));
202 Value = (Data[0] & 0xF0) >> 4;
203 Slots.push_back(static_cast<VFTableSlotKind>(Value));
206 Data = Data.slice(1);
209 return VFTableShapeRecord(Slots);
212 ErrorOr<TypeServer2Record>
213 TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
214 const Layout *L = nullptr;
216 CV_DESERIALIZE(Data, L, Name);
217 return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
220 ErrorOr<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind,
221 ArrayRef<uint8_t> &Data) {
222 const Layout *L = nullptr;
224 CV_DESERIALIZE(Data, L, Name);
225 return StringIdRecord(L->id, Name);
228 ErrorOr<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
229 ArrayRef<uint8_t> &Data) {
230 const Layout *L = nullptr;
232 CV_DESERIALIZE(Data, L, Name);
233 return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
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);
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);
251 ErrorOr<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
252 ArrayRef<uint8_t> &Data) {
253 const Layout *L = nullptr;
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,
261 ErrorOr<OneMethodRecord> OneMethodRecord::deserialize(TypeRecordKind Kind,
262 ArrayRef<uint8_t> &Data) {
263 const Layout *L = nullptr;
265 int32_t VFTableOffset = -1;
267 CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset,
268 L->Attrs.isIntroducedVirtual()),
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,
276 // Validate the vftable offset.
277 if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
278 return std::make_error_code(std::errc::illegal_byte_sequence);
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()));
292 MethodOptions Options = L->Attrs.getFlags();
293 MethodKind MethKind = L->Attrs.getMethodKind();
294 MemberAccess Access = L->Attrs.getAccess();
296 Methods.emplace_back(L->Type, MethKind, Options, Access, VFTableOffset,
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);
304 return MethodOverloadListRecord(Methods);
307 ErrorOr<OverloadedMethodRecord>
308 OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
309 ArrayRef<uint8_t> &Data) {
310 const Layout *L = nullptr;
312 CV_DESERIALIZE(Data, L, Name);
313 return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
316 ErrorOr<DataMemberRecord>
317 DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
318 const Layout *L = nullptr;
321 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name);
322 return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
325 ErrorOr<StaticDataMemberRecord>
326 StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
327 ArrayRef<uint8_t> &Data) {
328 const Layout *L = nullptr;
330 CV_DESERIALIZE(Data, L, Name);
331 return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
334 ErrorOr<EnumeratorRecord>
335 EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
336 const Layout *L = nullptr;
339 CV_DESERIALIZE(Data, L, Value, Name);
340 return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
343 ErrorOr<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
344 ArrayRef<uint8_t> &Data) {
345 const Layout *L = nullptr;
346 if (auto EC = consumeObject(Data, L))
348 return VFPtrRecord(L->Type);
351 ErrorOr<BaseClassRecord> BaseClassRecord::deserialize(TypeRecordKind Kind,
352 ArrayRef<uint8_t> &Data) {
353 const Layout *L = nullptr;
355 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset));
356 return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
359 ErrorOr<VirtualBaseClassRecord>
360 VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
361 ArrayRef<uint8_t> &Data) {
362 const Layout *L = nullptr;
365 CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
366 return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
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);
378 //===----------------------------------------------------------------------===//
379 // Type index remapping
380 //===----------------------------------------------------------------------===//
382 static bool remapIndex(ArrayRef<TypeIndex> IndexMap, TypeIndex &Idx) {
383 // Simple types are unchanged.
386 unsigned MapPos = Idx.getIndex() - TypeIndex::FirstNonSimpleIndex;
387 if (MapPos < IndexMap.size()) {
388 Idx = IndexMap[MapPos];
392 // This type index is invalid. Remap this to "not translated by cvpack",
393 // and return failure.
394 Idx = TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct);
398 bool ModifierRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
399 return remapIndex(IndexMap, ModifiedType);
402 bool ProcedureRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
404 Success &= remapIndex(IndexMap, ReturnType);
405 Success &= remapIndex(IndexMap, ArgumentList);
409 bool MemberFunctionRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
411 Success &= remapIndex(IndexMap, ReturnType);
412 Success &= remapIndex(IndexMap, ClassType);
413 Success &= remapIndex(IndexMap, ThisType);
414 Success &= remapIndex(IndexMap, ArgumentList);
418 bool MemberFuncIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
420 Success &= remapIndex(IndexMap, ClassType);
421 Success &= remapIndex(IndexMap, FunctionType);
425 bool ArgListRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
427 for (TypeIndex &Str : StringIndices)
428 Success &= remapIndex(IndexMap, Str);
432 bool MemberPointerInfo::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
433 return remapIndex(IndexMap, ContainingType);
436 bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
438 Success &= remapIndex(IndexMap, ReferentType);
439 if (isPointerToMember())
440 Success &= MemberInfo.remapTypeIndices(IndexMap);
444 bool NestedTypeRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
445 return remapIndex(IndexMap, Type);
448 bool ArrayRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
450 Success &= remapIndex(IndexMap, ElementType);
451 Success &= remapIndex(IndexMap, IndexType);
455 bool TagRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
456 return remapIndex(IndexMap, FieldList);
459 bool ClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
461 Success &= TagRecord::remapTypeIndices(IndexMap);
462 Success &= remapIndex(IndexMap, DerivationList);
463 Success &= remapIndex(IndexMap, VTableShape);
467 bool EnumRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
469 Success &= TagRecord::remapTypeIndices(IndexMap);
470 Success &= remapIndex(IndexMap, UnderlyingType);
474 bool BitFieldRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
475 return remapIndex(IndexMap, Type);
478 bool VFTableShapeRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
482 bool TypeServer2Record::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
486 bool StringIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
487 return remapIndex(IndexMap, Id);
490 bool FuncIdRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
492 Success &= remapIndex(IndexMap, ParentScope);
493 Success &= remapIndex(IndexMap, FunctionType);
497 bool UdtSourceLineRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
499 Success &= remapIndex(IndexMap, UDT);
500 Success &= remapIndex(IndexMap, SourceFile);
504 bool UdtModSourceLineRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
506 Success &= remapIndex(IndexMap, UDT);
507 Success &= remapIndex(IndexMap, SourceFile);
511 bool BuildInfoRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
513 for (TypeIndex &Arg : ArgIndices)
514 Success &= remapIndex(IndexMap, Arg);
518 bool VFTableRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
520 Success &= remapIndex(IndexMap, CompleteClass);
521 Success &= remapIndex(IndexMap, OverriddenVFTable);
525 bool OneMethodRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
527 Success &= remapIndex(IndexMap, Type);
531 bool MethodOverloadListRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
533 for (OneMethodRecord &Meth : Methods)
534 if ((Success = Meth.remapTypeIndices(IndexMap)))
539 bool OverloadedMethodRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
540 return remapIndex(IndexMap, MethodList);
543 bool DataMemberRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
544 return remapIndex(IndexMap, Type);
547 bool StaticDataMemberRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
548 return remapIndex(IndexMap, Type);
551 bool EnumeratorRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
555 bool VFPtrRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
556 return remapIndex(IndexMap, Type);
559 bool BaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
560 return remapIndex(IndexMap, Type);
563 bool VirtualBaseClassRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
565 Success &= remapIndex(IndexMap, BaseType);
566 Success &= remapIndex(IndexMap, VBPtrType);
570 bool ListContinuationRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
571 return remapIndex(IndexMap, ContinuationIndex);