1 //===-- PdbUtil.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 "PdbUtil.h"
11 
12 #include "DWARFLocationExpression.h"
13 #include "PdbIndex.h"
14 #include "PdbSymUid.h"
15 
16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
19 
20 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
21 #include "lldb/Utility/LLDBAssert.h"
22 #include "lldb/lldb-enumerations.h"
23 
24 using namespace lldb_private;
25 using namespace lldb_private::npdb;
26 using namespace llvm::codeview;
27 using namespace llvm::pdb;
28 
29 static Variable::RangeList
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)30 MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
31               llvm::ArrayRef<LocalVariableAddrGap> gaps) {
32   lldb::addr_t start =
33       index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
34   lldb::addr_t end = start + range.Range;
35 
36   Variable::RangeList result;
37   while (!gaps.empty()) {
38     const LocalVariableAddrGap &gap = gaps.front();
39 
40     lldb::addr_t size = gap.GapStartOffset - start;
41     result.Append(start, size);
42     start += gap.Range;
43     gaps = gaps.drop_front();
44   }
45 
46   result.Append(start, end);
47   return result;
48 }
49 
create(CVType type)50 CVTagRecord CVTagRecord::create(CVType type) {
51   assert(IsTagRecord(type) && "type is not a tag record!");
52   switch (type.kind()) {
53   case LF_CLASS:
54   case LF_STRUCTURE:
55   case LF_INTERFACE: {
56     ClassRecord cr;
57     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
58     return CVTagRecord(std::move(cr));
59   }
60   case LF_UNION: {
61     UnionRecord ur;
62     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
63     return CVTagRecord(std::move(ur));
64   }
65   case LF_ENUM: {
66     EnumRecord er;
67     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
68     return CVTagRecord(std::move(er));
69   }
70   default:
71     llvm_unreachable("Unreachable!");
72   }
73 }
74 
CVTagRecord(ClassRecord && c)75 CVTagRecord::CVTagRecord(ClassRecord &&c)
76     : cvclass(std::move(c)),
77       m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)78 CVTagRecord::CVTagRecord(UnionRecord &&u)
79     : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)80 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
81 
CVSymToPDBSym(SymbolKind kind)82 PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
83   switch (kind) {
84   case S_COMPILE3:
85   case S_OBJNAME:
86     return PDB_SymType::CompilandDetails;
87   case S_ENVBLOCK:
88     return PDB_SymType::CompilandEnv;
89   case S_THUNK32:
90   case S_TRAMPOLINE:
91     return PDB_SymType::Thunk;
92   case S_COFFGROUP:
93     return PDB_SymType::CoffGroup;
94   case S_EXPORT:
95     return PDB_SymType::Export;
96   case S_LPROC32:
97   case S_GPROC32:
98   case S_LPROC32_DPC:
99     return PDB_SymType::Function;
100   case S_PUB32:
101     return PDB_SymType::PublicSymbol;
102   case S_INLINESITE:
103     return PDB_SymType::InlineSite;
104   case S_LOCAL:
105   case S_BPREL32:
106   case S_REGREL32:
107   case S_MANCONSTANT:
108   case S_CONSTANT:
109   case S_LDATA32:
110   case S_GDATA32:
111   case S_LMANDATA:
112   case S_GMANDATA:
113   case S_LTHREAD32:
114   case S_GTHREAD32:
115     return PDB_SymType::Data;
116   case S_BLOCK32:
117     return PDB_SymType::Block;
118   case S_LABEL32:
119     return PDB_SymType::Label;
120   case S_CALLSITEINFO:
121     return PDB_SymType::CallSite;
122   case S_HEAPALLOCSITE:
123     return PDB_SymType::HeapAllocationSite;
124   case S_CALLEES:
125     return PDB_SymType::Callee;
126   case S_CALLERS:
127     return PDB_SymType::Caller;
128   default:
129     lldbassert(false && "Invalid symbol record kind!");
130   }
131   return PDB_SymType::None;
132 }
133 
CVTypeToPDBType(TypeLeafKind kind)134 PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
135   switch (kind) {
136   case LF_ARRAY:
137     return PDB_SymType::ArrayType;
138   case LF_ARGLIST:
139     return PDB_SymType::FunctionSig;
140   case LF_BCLASS:
141     return PDB_SymType::BaseClass;
142   case LF_BINTERFACE:
143     return PDB_SymType::BaseInterface;
144   case LF_CLASS:
145   case LF_STRUCTURE:
146   case LF_INTERFACE:
147   case LF_UNION:
148     return PDB_SymType::UDT;
149   case LF_POINTER:
150     return PDB_SymType::PointerType;
151   case LF_ENUM:
152     return PDB_SymType::Enum;
153   case LF_PROCEDURE:
154     return PDB_SymType::FunctionSig;
155   case LF_BITFIELD:
156     return PDB_SymType::BuiltinType;
157   default:
158     lldbassert(false && "Invalid type record kind!");
159   }
160   return PDB_SymType::None;
161 }
162 
SymbolHasAddress(const CVSymbol & sym)163 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
164   switch (sym.kind()) {
165   case S_GPROC32:
166   case S_LPROC32:
167   case S_GPROC32_ID:
168   case S_LPROC32_ID:
169   case S_LPROC32_DPC:
170   case S_LPROC32_DPC_ID:
171   case S_THUNK32:
172   case S_TRAMPOLINE:
173   case S_COFFGROUP:
174   case S_BLOCK32:
175   case S_LABEL32:
176   case S_CALLSITEINFO:
177   case S_HEAPALLOCSITE:
178   case S_LDATA32:
179   case S_GDATA32:
180   case S_LMANDATA:
181   case S_GMANDATA:
182   case S_LTHREAD32:
183   case S_GTHREAD32:
184     return true;
185   default:
186     return false;
187   }
188 }
189 
SymbolIsCode(const CVSymbol & sym)190 bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
191   switch (sym.kind()) {
192   case S_GPROC32:
193   case S_LPROC32:
194   case S_GPROC32_ID:
195   case S_LPROC32_ID:
196   case S_LPROC32_DPC:
197   case S_LPROC32_DPC_ID:
198   case S_THUNK32:
199   case S_TRAMPOLINE:
200   case S_COFFGROUP:
201   case S_BLOCK32:
202     return true;
203   default:
204     return false;
205   }
206 }
207 
createRecord(const CVSymbol & sym)208 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
209   RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
210   cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
211   return record;
212 }
213 
214 template <typename RecordT>
GetSegmentAndOffset(const CVSymbol & sym)215 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
216   RecordT record = createRecord<RecordT>(sym);
217   return {record.Segment, record.CodeOffset};
218 }
219 
220 template <>
GetSegmentAndOffset(const CVSymbol & sym)221 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
222   TrampolineSym record = createRecord<TrampolineSym>(sym);
223   return {record.ThunkSection, record.ThunkOffset};
224 }
225 
GetSegmentAndOffset(const CVSymbol & sym)226 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
227   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
228   return {record.Segment, record.Offset};
229 }
230 
231 template <>
GetSegmentAndOffset(const CVSymbol & sym)232 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
233   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
234   return {record.Segment, record.Offset};
235 }
236 
GetSegmentAndOffset(const CVSymbol & sym)237 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
238   DataSym record = createRecord<DataSym>(sym);
239   return {record.Segment, record.DataOffset};
240 }
241 
242 template <>
GetSegmentAndOffset(const CVSymbol & sym)243 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
244   ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
245   return {record.Segment, record.DataOffset};
246 }
247 
GetSegmentAndOffset(const CVSymbol & sym)248 SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
249   switch (sym.kind()) {
250   case S_GPROC32:
251   case S_LPROC32:
252   case S_GPROC32_ID:
253   case S_LPROC32_ID:
254   case S_LPROC32_DPC:
255   case S_LPROC32_DPC_ID:
256     return ::GetSegmentAndOffset<ProcSym>(sym);
257   case S_THUNK32:
258     return ::GetSegmentAndOffset<Thunk32Sym>(sym);
259     break;
260   case S_TRAMPOLINE:
261     return ::GetSegmentAndOffset<TrampolineSym>(sym);
262     break;
263   case S_COFFGROUP:
264     return ::GetSegmentAndOffset<CoffGroupSym>(sym);
265     break;
266   case S_BLOCK32:
267     return ::GetSegmentAndOffset<BlockSym>(sym);
268     break;
269   case S_LABEL32:
270     return ::GetSegmentAndOffset<LabelSym>(sym);
271     break;
272   case S_CALLSITEINFO:
273     return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
274     break;
275   case S_HEAPALLOCSITE:
276     return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
277     break;
278   case S_LDATA32:
279   case S_GDATA32:
280   case S_LMANDATA:
281   case S_GMANDATA:
282     return ::GetSegmentAndOffset<DataSym>(sym);
283     break;
284   case S_LTHREAD32:
285   case S_GTHREAD32:
286     return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
287     break;
288   default:
289     lldbassert(false && "Record does not have a segment/offset!");
290   }
291   return {0, 0};
292 }
293 
294 template <typename RecordT>
GetSegmentOffsetAndLength(const CVSymbol & sym)295 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
296   RecordT record = createRecord<RecordT>(sym);
297   return {record.Segment, record.CodeOffset, record.CodeSize};
298 }
299 
300 template <>
301 SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)302 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
303   TrampolineSym record = createRecord<TrampolineSym>(sym);
304   return {record.ThunkSection, record.ThunkOffset, record.Size};
305 }
306 
307 template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)308 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
309   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
310   return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
311 }
312 
313 template <>
314 SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)315 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
316   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
317   return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
318 }
319 
320 SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)321 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
322   switch (sym.kind()) {
323   case S_GPROC32:
324   case S_LPROC32:
325   case S_GPROC32_ID:
326   case S_LPROC32_ID:
327   case S_LPROC32_DPC:
328   case S_LPROC32_DPC_ID:
329     return ::GetSegmentOffsetAndLength<ProcSym>(sym);
330   case S_THUNK32:
331     return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
332     break;
333   case S_TRAMPOLINE:
334     return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
335     break;
336   case S_COFFGROUP:
337     return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
338     break;
339   case S_BLOCK32:
340     return ::GetSegmentOffsetAndLength<BlockSym>(sym);
341     break;
342   default:
343     lldbassert(false && "Record does not have a segment/offset/length triple!");
344   }
345   return {0, 0, 0};
346 }
347 
IsForwardRefUdt(CVType cvt)348 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
349   ClassRecord cr;
350   UnionRecord ur;
351   EnumRecord er;
352   switch (cvt.kind()) {
353   case LF_CLASS:
354   case LF_STRUCTURE:
355   case LF_INTERFACE:
356     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
357     return cr.isForwardRef();
358   case LF_UNION:
359     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
360     return ur.isForwardRef();
361   case LF_ENUM:
362     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
363     return er.isForwardRef();
364   default:
365     return false;
366   }
367 }
368 
IsTagRecord(llvm::codeview::CVType cvt)369 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
370   switch (cvt.kind()) {
371   case LF_CLASS:
372   case LF_STRUCTURE:
373   case LF_UNION:
374   case LF_ENUM:
375     return true;
376   default:
377     return false;
378   }
379 }
380 
IsClassStructUnion(llvm::codeview::CVType cvt)381 bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
382   switch (cvt.kind()) {
383   case LF_CLASS:
384   case LF_STRUCTURE:
385   case LF_UNION:
386     return true;
387   default:
388     return false;
389   }
390 }
391 
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)392 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
393                                          TpiStream &tpi) {
394   if (id.is_ipi || id.index.isSimple())
395     return false;
396   return IsForwardRefUdt(tpi.getType(id.index));
397 }
398 
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)399 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
400   if (id.is_ipi || id.index.isSimple())
401     return false;
402   return IsTagRecord(tpi.getType(id.index));
403 }
404 
405 lldb::AccessType
TranslateMemberAccess(MemberAccess access)406 lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
407   switch (access) {
408   case MemberAccess::Private:
409     return lldb::eAccessPrivate;
410   case MemberAccess::Protected:
411     return lldb::eAccessProtected;
412   case MemberAccess::Public:
413     return lldb::eAccessPublic;
414   case MemberAccess::None:
415     return lldb::eAccessNone;
416   }
417   llvm_unreachable("unreachable");
418 }
419 
GetFieldListIndex(CVType cvt)420 TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
421   switch (cvt.kind()) {
422   case LF_CLASS:
423   case LF_STRUCTURE:
424   case LF_INTERFACE: {
425     ClassRecord cr;
426     cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
427     return cr.FieldList;
428   }
429   case LF_UNION: {
430     UnionRecord ur;
431     cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
432     return ur.FieldList;
433   }
434   case LF_ENUM: {
435     EnumRecord er;
436     cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
437     return er.FieldList;
438   }
439   default:
440     llvm_unreachable("Unreachable!");
441   }
442 }
443 
LookThroughModifierRecord(CVType modifier)444 TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
445   lldbassert(modifier.kind() == LF_MODIFIER);
446   ModifierRecord mr;
447   llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
448   return mr.ModifiedType;
449 }
450 
DropNameScope(llvm::StringRef name)451 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
452   return MSVCUndecoratedNameParser::DropScope(name);
453 }
454 
GetVariableNameInfo(CVSymbol sym)455 VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
456   VariableInfo result;
457 
458   if (sym.kind() == S_REGREL32) {
459     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
460     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
461     result.type = reg.Type;
462     result.name = reg.Name;
463     return result;
464   }
465 
466   if (sym.kind() == S_REGISTER) {
467     RegisterSym reg(SymbolRecordKind::RegisterSym);
468     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
469     result.type = reg.Index;
470     result.name = reg.Name;
471     return result;
472   }
473 
474   if (sym.kind() == S_LOCAL) {
475     LocalSym local(SymbolRecordKind::LocalSym);
476     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
477     result.type = local.Type;
478     result.name = local.Name;
479     return result;
480   }
481 
482   if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
483     DataSym data(SymbolRecordKind::DataSym);
484     cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
485     result.type = data.Type;
486     result.name = data.Name;
487     return result;
488   }
489 
490   if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
491     ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
492     cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
493     result.type = data.Type;
494     result.name = data.Name;
495     return result;
496   }
497 
498   if (sym.kind() == S_CONSTANT) {
499     ConstantSym constant(SymbolRecordKind::ConstantSym);
500     cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
501     result.type = constant.Type;
502     result.name = constant.Name;
503     return result;
504   }
505 
506   lldbassert(false && "Invalid variable record kind!");
507   return {};
508 }
509 
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,lldb::ModuleSP module)510 VariableInfo lldb_private::npdb::GetVariableLocationInfo(
511     PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) {
512 
513   CVSymbol sym = index.ReadSymbolRecord(var_id);
514 
515   VariableInfo result = GetVariableNameInfo(sym);
516 
517   if (sym.kind() == S_REGREL32) {
518     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
519     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
520     result.location =
521         MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
522     result.ranges.emplace();
523     return result;
524   }
525 
526   if (sym.kind() == S_REGISTER) {
527     RegisterSym reg(SymbolRecordKind::RegisterSym);
528     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
529     result.location = MakeEnregisteredLocationExpression(reg.Register, module);
530     result.ranges.emplace();
531     return result;
532   }
533 
534   if (sym.kind() == S_LOCAL) {
535     LocalSym local(SymbolRecordKind::LocalSym);
536     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
537 
538     PdbCompilandSymId loc_specifier_id(var_id.modi,
539                                        var_id.offset + sym.RecordData.size());
540     CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
541     if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
542       DefRangeFramePointerRelSym loc(
543           SymbolRecordKind::DefRangeFramePointerRelSym);
544       cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
545           loc_specifier_cvs, loc));
546       // FIXME: The register needs to come from the S_FRAMEPROC symbol.
547       result.location =
548           MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module);
549       result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
550     } else {
551       // FIXME: Handle other kinds
552     }
553     return result;
554   }
555   llvm_unreachable("Symbol is not a local variable!");
556   return result;
557 }
558 
559 lldb::BasicType
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)560 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
561   switch (kind) {
562   case SimpleTypeKind::Boolean128:
563   case SimpleTypeKind::Boolean16:
564   case SimpleTypeKind::Boolean32:
565   case SimpleTypeKind::Boolean64:
566   case SimpleTypeKind::Boolean8:
567     return lldb::eBasicTypeBool;
568   case SimpleTypeKind::Byte:
569   case SimpleTypeKind::UnsignedCharacter:
570     return lldb::eBasicTypeUnsignedChar;
571   case SimpleTypeKind::NarrowCharacter:
572     return lldb::eBasicTypeChar;
573   case SimpleTypeKind::SignedCharacter:
574   case SimpleTypeKind::SByte:
575     return lldb::eBasicTypeSignedChar;
576   case SimpleTypeKind::Character16:
577     return lldb::eBasicTypeChar16;
578   case SimpleTypeKind::Character32:
579     return lldb::eBasicTypeChar32;
580   case SimpleTypeKind::Complex80:
581     return lldb::eBasicTypeLongDoubleComplex;
582   case SimpleTypeKind::Complex64:
583     return lldb::eBasicTypeDoubleComplex;
584   case SimpleTypeKind::Complex32:
585     return lldb::eBasicTypeFloatComplex;
586   case SimpleTypeKind::Float128:
587   case SimpleTypeKind::Float80:
588     return lldb::eBasicTypeLongDouble;
589   case SimpleTypeKind::Float64:
590     return lldb::eBasicTypeDouble;
591   case SimpleTypeKind::Float32:
592     return lldb::eBasicTypeFloat;
593   case SimpleTypeKind::Float16:
594     return lldb::eBasicTypeHalf;
595   case SimpleTypeKind::Int128:
596     return lldb::eBasicTypeInt128;
597   case SimpleTypeKind::Int64:
598   case SimpleTypeKind::Int64Quad:
599     return lldb::eBasicTypeLongLong;
600   case SimpleTypeKind::Int32:
601     return lldb::eBasicTypeInt;
602   case SimpleTypeKind::Int16:
603   case SimpleTypeKind::Int16Short:
604     return lldb::eBasicTypeShort;
605   case SimpleTypeKind::UInt128:
606     return lldb::eBasicTypeUnsignedInt128;
607   case SimpleTypeKind::UInt64:
608   case SimpleTypeKind::UInt64Quad:
609     return lldb::eBasicTypeUnsignedLongLong;
610   case SimpleTypeKind::HResult:
611   case SimpleTypeKind::UInt32:
612     return lldb::eBasicTypeUnsignedInt;
613   case SimpleTypeKind::UInt16:
614   case SimpleTypeKind::UInt16Short:
615     return lldb::eBasicTypeUnsignedShort;
616   case SimpleTypeKind::Int32Long:
617     return lldb::eBasicTypeLong;
618   case SimpleTypeKind::UInt32Long:
619     return lldb::eBasicTypeUnsignedLong;
620   case SimpleTypeKind::Void:
621     return lldb::eBasicTypeVoid;
622   case SimpleTypeKind::WideCharacter:
623     return lldb::eBasicTypeWChar;
624   default:
625     return lldb::eBasicTypeInvalid;
626   }
627 }
628 
GetTypeSizeForSimpleKind(SimpleTypeKind kind)629 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
630   switch (kind) {
631   case SimpleTypeKind::Boolean128:
632   case SimpleTypeKind::Int128:
633   case SimpleTypeKind::UInt128:
634   case SimpleTypeKind::Float128:
635     return 16;
636   case SimpleTypeKind::Complex80:
637   case SimpleTypeKind::Float80:
638     return 10;
639   case SimpleTypeKind::Boolean64:
640   case SimpleTypeKind::Complex64:
641   case SimpleTypeKind::UInt64:
642   case SimpleTypeKind::UInt64Quad:
643   case SimpleTypeKind::Float64:
644   case SimpleTypeKind::Int64:
645   case SimpleTypeKind::Int64Quad:
646     return 8;
647   case SimpleTypeKind::Boolean32:
648   case SimpleTypeKind::Character32:
649   case SimpleTypeKind::Complex32:
650   case SimpleTypeKind::Float32:
651   case SimpleTypeKind::Int32:
652   case SimpleTypeKind::Int32Long:
653   case SimpleTypeKind::UInt32Long:
654   case SimpleTypeKind::HResult:
655   case SimpleTypeKind::UInt32:
656     return 4;
657   case SimpleTypeKind::Boolean16:
658   case SimpleTypeKind::Character16:
659   case SimpleTypeKind::Float16:
660   case SimpleTypeKind::Int16:
661   case SimpleTypeKind::Int16Short:
662   case SimpleTypeKind::UInt16:
663   case SimpleTypeKind::UInt16Short:
664   case SimpleTypeKind::WideCharacter:
665     return 2;
666   case SimpleTypeKind::Boolean8:
667   case SimpleTypeKind::Byte:
668   case SimpleTypeKind::UnsignedCharacter:
669   case SimpleTypeKind::NarrowCharacter:
670   case SimpleTypeKind::SignedCharacter:
671   case SimpleTypeKind::SByte:
672     return 1;
673   case SimpleTypeKind::Void:
674   default:
675     return 0;
676   }
677 }
678 
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)679 PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
680                                                      TpiStream &tpi) {
681   if (id.index.isSimple())
682     return id;
683 
684   CVType cvt = tpi.getType(id.index);
685 
686   // Only tag records have a best and a worst record.
687   if (!IsTagRecord(cvt))
688     return id;
689 
690   // Tag records that are not forward decls are full decls, hence they are the
691   // best.
692   if (!IsForwardRefUdt(cvt))
693     return id;
694 
695   return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
696 }
697 
GetSizeOfTypeInternal(CVType cvt)698 template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
699   RecordType record;
700   llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
701   return record.getSize();
702 }
703 
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)704 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
705                                          llvm::pdb::TpiStream &tpi) {
706   if (id.index.isSimple()) {
707     switch (id.index.getSimpleMode()) {
708     case SimpleTypeMode::Direct:
709       return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
710     case SimpleTypeMode::NearPointer32:
711     case SimpleTypeMode::FarPointer32:
712       return 4;
713     case SimpleTypeMode::NearPointer64:
714       return 8;
715     case SimpleTypeMode::NearPointer128:
716       return 16;
717     default:
718       break;
719     }
720     return 0;
721   }
722 
723   TypeIndex index = id.index;
724   if (IsForwardRefUdt(index, tpi))
725     index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
726 
727   CVType cvt = tpi.getType(index);
728   switch (cvt.kind()) {
729   case LF_MODIFIER:
730     return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
731   case LF_ENUM: {
732     EnumRecord record;
733     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
734     return GetSizeOfType({record.UnderlyingType}, tpi);
735   }
736   case LF_POINTER:
737     return GetSizeOfTypeInternal<PointerRecord>(cvt);
738   case LF_ARRAY:
739     return GetSizeOfTypeInternal<ArrayRecord>(cvt);
740   case LF_CLASS:
741   case LF_STRUCTURE:
742   case LF_INTERFACE:
743     return GetSizeOfTypeInternal<ClassRecord>(cvt);
744   case LF_UNION:
745     return GetSizeOfTypeInternal<UnionRecord>(cvt);
746   default:
747     break;
748   }
749   return 0;
750 }
751