1 //===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "DWARFLocationExpression.h"
13 #include "PdbSymUid.h"
15 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
16 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
17 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
18 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
21 #include "lldb/Symbol/Block.h"
22 #include "lldb/Utility/LLDBAssert.h"
23 #include "lldb/lldb-enumerations.h"
25 using namespace lldb_private;
26 using namespace lldb_private::npdb;
27 using namespace llvm::codeview;
28 using namespace llvm::pdb;
30 static Variable::RangeList
31 MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
32 llvm::ArrayRef<LocalVariableAddrGap> gaps) {
34 index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
35 lldb::addr_t end = start + range.Range;
37 Variable::RangeList result;
38 while (!gaps.empty()) {
39 const LocalVariableAddrGap &gap = gaps.front();
41 lldb::addr_t size = gap.GapStartOffset - start;
42 result.Append(start, size);
44 gaps = gaps.drop_front();
47 result.Append(start, end - start);
51 CVTagRecord CVTagRecord::create(CVType type) {
52 assert(IsTagRecord(type) && "type is not a tag record!");
53 switch (type.kind()) {
58 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
59 return CVTagRecord(std::move(cr));
63 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
64 return CVTagRecord(std::move(ur));
68 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
69 return CVTagRecord(std::move(er));
72 llvm_unreachable("Unreachable!");
76 CVTagRecord::CVTagRecord(ClassRecord &&c)
77 : cvclass(std::move(c)),
78 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
79 CVTagRecord::CVTagRecord(UnionRecord &&u)
80 : cvunion(std::move(u)), m_kind(Union) {}
81 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
83 PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
87 return PDB_SymType::CompilandDetails;
89 return PDB_SymType::CompilandEnv;
92 return PDB_SymType::Thunk;
94 return PDB_SymType::CoffGroup;
96 return PDB_SymType::Export;
100 return PDB_SymType::Function;
102 return PDB_SymType::PublicSymbol;
104 return PDB_SymType::InlineSite;
116 return PDB_SymType::Data;
118 return PDB_SymType::Block;
120 return PDB_SymType::Label;
122 return PDB_SymType::CallSite;
123 case S_HEAPALLOCSITE:
124 return PDB_SymType::HeapAllocationSite;
126 return PDB_SymType::Callee;
128 return PDB_SymType::Caller;
130 lldbassert(false && "Invalid symbol record kind!");
132 return PDB_SymType::None;
135 PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
138 return PDB_SymType::ArrayType;
140 return PDB_SymType::FunctionSig;
142 return PDB_SymType::BaseClass;
144 return PDB_SymType::BaseInterface;
149 return PDB_SymType::UDT;
151 return PDB_SymType::PointerType;
153 return PDB_SymType::Enum;
155 return PDB_SymType::FunctionSig;
157 return PDB_SymType::BuiltinType;
159 lldbassert(false && "Invalid type record kind!");
161 return PDB_SymType::None;
164 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
165 switch (sym.kind()) {
171 case S_LPROC32_DPC_ID:
178 case S_HEAPALLOCSITE:
191 bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
192 switch (sym.kind()) {
198 case S_LPROC32_DPC_ID:
209 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
210 RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
211 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
215 template <typename RecordT>
216 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
217 RecordT record = createRecord<RecordT>(sym);
218 return {record.Segment, record.CodeOffset};
222 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
223 TrampolineSym record = createRecord<TrampolineSym>(sym);
224 return {record.ThunkSection, record.ThunkOffset};
227 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
228 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
229 return {record.Segment, record.Offset};
233 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
234 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
235 return {record.Segment, record.Offset};
238 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
239 DataSym record = createRecord<DataSym>(sym);
240 return {record.Segment, record.DataOffset};
244 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
245 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
246 return {record.Segment, record.DataOffset};
249 SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
250 switch (sym.kind()) {
256 case S_LPROC32_DPC_ID:
257 return ::GetSegmentAndOffset<ProcSym>(sym);
259 return ::GetSegmentAndOffset<Thunk32Sym>(sym);
262 return ::GetSegmentAndOffset<TrampolineSym>(sym);
265 return ::GetSegmentAndOffset<CoffGroupSym>(sym);
268 return ::GetSegmentAndOffset<BlockSym>(sym);
271 return ::GetSegmentAndOffset<LabelSym>(sym);
274 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
276 case S_HEAPALLOCSITE:
277 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
283 return ::GetSegmentAndOffset<DataSym>(sym);
287 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
290 lldbassert(false && "Record does not have a segment/offset!");
295 template <typename RecordT>
296 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
297 RecordT record = createRecord<RecordT>(sym);
298 return {record.Segment, record.CodeOffset, record.CodeSize};
303 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
304 TrampolineSym record = createRecord<TrampolineSym>(sym);
305 return {record.ThunkSection, record.ThunkOffset, record.Size};
309 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
310 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
311 return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
316 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
317 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
318 return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
322 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
323 switch (sym.kind()) {
329 case S_LPROC32_DPC_ID:
330 return ::GetSegmentOffsetAndLength<ProcSym>(sym);
332 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
335 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
338 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
341 return ::GetSegmentOffsetAndLength<BlockSym>(sym);
344 lldbassert(false && "Record does not have a segment/offset/length triple!");
349 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
353 switch (cvt.kind()) {
357 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
358 return cr.isForwardRef();
360 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
361 return ur.isForwardRef();
363 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
364 return er.isForwardRef();
370 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
371 switch (cvt.kind()) {
382 bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
383 switch (cvt.kind()) {
393 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
395 if (id.is_ipi || id.index.isSimple())
397 return IsForwardRefUdt(tpi.getType(id.index));
400 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
401 if (id.is_ipi || id.index.isSimple())
403 return IsTagRecord(tpi.getType(id.index));
407 lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
409 case MemberAccess::Private:
410 return lldb::eAccessPrivate;
411 case MemberAccess::Protected:
412 return lldb::eAccessProtected;
413 case MemberAccess::Public:
414 return lldb::eAccessPublic;
415 case MemberAccess::None:
416 return lldb::eAccessNone;
418 llvm_unreachable("unreachable");
421 TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
422 switch (cvt.kind()) {
427 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
432 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
437 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
441 llvm_unreachable("Unreachable!");
445 TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
446 lldbassert(modifier.kind() == LF_MODIFIER);
448 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
449 return mr.ModifiedType;
452 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
453 return MSVCUndecoratedNameParser::DropScope(name);
456 VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
459 if (sym.kind() == S_REGREL32) {
460 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
461 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
462 result.type = reg.Type;
463 result.name = reg.Name;
467 if (sym.kind() == S_REGISTER) {
468 RegisterSym reg(SymbolRecordKind::RegisterSym);
469 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
470 result.type = reg.Index;
471 result.name = reg.Name;
475 if (sym.kind() == S_LOCAL) {
476 LocalSym local(SymbolRecordKind::LocalSym);
477 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
478 result.type = local.Type;
479 result.name = local.Name;
483 if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
484 DataSym data(SymbolRecordKind::DataSym);
485 cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
486 result.type = data.Type;
487 result.name = data.Name;
491 if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
492 ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
493 cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
494 result.type = data.Type;
495 result.name = data.Name;
499 if (sym.kind() == S_CONSTANT) {
500 ConstantSym constant(SymbolRecordKind::ConstantSym);
501 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
502 result.type = constant.Type;
503 result.name = constant.Name;
507 lldbassert(false && "Invalid variable record kind!");
511 static llvm::FixedStreamArray<FrameData>::Iterator
512 GetCorrespondingFrameData(lldb::addr_t load_addr,
513 const DebugFrameDataSubsectionRef &fpo_data,
514 const Variable::RangeList &ranges) {
515 lldbassert(!ranges.IsEmpty());
517 // assume that all variable ranges correspond to one frame data
518 using RangeListEntry = Variable::RangeList::Entry;
519 const RangeListEntry &range = ranges.GetEntryRef(0);
521 auto it = fpo_data.begin();
523 // start by searching first frame data range containing variable range
524 for (; it != fpo_data.end(); ++it) {
525 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
527 if (fd_range.Contains(range)) {
532 // then first most nested entry that still contains variable range
534 for (; it != fpo_data.end(); ++it) {
535 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
537 if (!fd_range.Contains(range)) {
546 static bool GetFrameDataProgram(PdbIndex &index,
547 const Variable::RangeList &ranges,
548 llvm::StringRef &out_program) {
549 const DebugFrameDataSubsectionRef &new_fpo_data =
550 index.dbi().getNewFpoRecords();
553 GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
554 if (frame_data_it == new_fpo_data.end())
557 PDBStringTable &strings = cantFail(index.pdb().getStringTable());
558 out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc));
562 static RegisterId GetBaseFrameRegister(PdbIndex &index,
563 PdbCompilandSymId frame_proc_id,
565 CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
566 lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC);
568 FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
569 cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
572 CPUType cpu_type = index.compilands()
573 .GetCompiland(frame_proc_id.modi)
574 ->m_compile_opts->Machine;
576 return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
577 : frame_proc.getLocalFramePtrReg(cpu_type);
580 VariableInfo lldb_private::npdb::GetVariableLocationInfo(
581 PdbIndex &index, PdbCompilandSymId var_id, Block &block,
582 lldb::ModuleSP module) {
584 CVSymbol sym = index.ReadSymbolRecord(var_id);
586 VariableInfo result = GetVariableNameInfo(sym);
588 if (sym.kind() == S_REGREL32) {
589 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
590 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
592 MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
593 result.ranges.emplace();
597 if (sym.kind() == S_REGISTER) {
598 RegisterSym reg(SymbolRecordKind::RegisterSym);
599 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
600 result.location = MakeEnregisteredLocationExpression(reg.Register, module);
601 result.ranges.emplace();
605 if (sym.kind() == S_LOCAL) {
606 LocalSym local(SymbolRecordKind::LocalSym);
607 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
609 PdbCompilandSymId loc_specifier_id(var_id.modi,
610 var_id.offset + sym.RecordData.size());
611 CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
612 if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
613 DefRangeFramePointerRelSym loc(
614 SymbolRecordKind::DefRangeFramePointerRelSym);
615 cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
616 loc_specifier_cvs, loc));
618 Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
620 // TODO: may be better to pass function scope and not lookup it every
621 // time? find nearest parent function block
623 while (cur->GetParent()) {
624 cur = cur->GetParent();
626 PdbCompilandSymId func_scope_id =
627 PdbSymUid(cur->GetID()).asCompilandSym();
628 CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
629 lldbassert(func_block_cvs.kind() == S_GPROC32 ||
630 func_block_cvs.kind() == S_LPROC32);
632 PdbCompilandSymId frame_proc_id(
633 func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
636 ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
637 RegisterId base_reg =
638 GetBaseFrameRegister(index, frame_proc_id, is_parameter);
640 if (base_reg == RegisterId::VFRAME) {
641 llvm::StringRef program;
642 if (GetFrameDataProgram(index, ranges, program)) {
644 MakeVFrameRelLocationExpression(program, loc.Offset, module);
645 result.ranges = std::move(ranges);
651 MakeRegRelLocationExpression(base_reg, loc.Offset, module);
652 result.ranges = std::move(ranges);
654 } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) {
655 DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
656 cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
657 loc_specifier_cvs, loc));
659 Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
661 RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
663 if (base_reg == RegisterId::VFRAME) {
664 llvm::StringRef program;
665 if (GetFrameDataProgram(index, ranges, program)) {
666 result.location = MakeVFrameRelLocationExpression(
667 program, loc.Hdr.BasePointerOffset, module);
668 result.ranges = std::move(ranges);
673 result.location = MakeRegRelLocationExpression(
674 base_reg, loc.Hdr.BasePointerOffset, module);
675 result.ranges = std::move(ranges);
679 // FIXME: Handle other kinds
682 llvm_unreachable("Symbol is not a local variable!");
687 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
689 case SimpleTypeKind::Boolean128:
690 case SimpleTypeKind::Boolean16:
691 case SimpleTypeKind::Boolean32:
692 case SimpleTypeKind::Boolean64:
693 case SimpleTypeKind::Boolean8:
694 return lldb::eBasicTypeBool;
695 case SimpleTypeKind::Byte:
696 case SimpleTypeKind::UnsignedCharacter:
697 return lldb::eBasicTypeUnsignedChar;
698 case SimpleTypeKind::NarrowCharacter:
699 return lldb::eBasicTypeChar;
700 case SimpleTypeKind::SignedCharacter:
701 case SimpleTypeKind::SByte:
702 return lldb::eBasicTypeSignedChar;
703 case SimpleTypeKind::Character16:
704 return lldb::eBasicTypeChar16;
705 case SimpleTypeKind::Character32:
706 return lldb::eBasicTypeChar32;
707 case SimpleTypeKind::Complex80:
708 return lldb::eBasicTypeLongDoubleComplex;
709 case SimpleTypeKind::Complex64:
710 return lldb::eBasicTypeDoubleComplex;
711 case SimpleTypeKind::Complex32:
712 return lldb::eBasicTypeFloatComplex;
713 case SimpleTypeKind::Float128:
714 case SimpleTypeKind::Float80:
715 return lldb::eBasicTypeLongDouble;
716 case SimpleTypeKind::Float64:
717 return lldb::eBasicTypeDouble;
718 case SimpleTypeKind::Float32:
719 return lldb::eBasicTypeFloat;
720 case SimpleTypeKind::Float16:
721 return lldb::eBasicTypeHalf;
722 case SimpleTypeKind::Int128:
723 return lldb::eBasicTypeInt128;
724 case SimpleTypeKind::Int64:
725 case SimpleTypeKind::Int64Quad:
726 return lldb::eBasicTypeLongLong;
727 case SimpleTypeKind::Int32:
728 return lldb::eBasicTypeInt;
729 case SimpleTypeKind::Int16:
730 case SimpleTypeKind::Int16Short:
731 return lldb::eBasicTypeShort;
732 case SimpleTypeKind::UInt128:
733 return lldb::eBasicTypeUnsignedInt128;
734 case SimpleTypeKind::UInt64:
735 case SimpleTypeKind::UInt64Quad:
736 return lldb::eBasicTypeUnsignedLongLong;
737 case SimpleTypeKind::HResult:
738 case SimpleTypeKind::UInt32:
739 return lldb::eBasicTypeUnsignedInt;
740 case SimpleTypeKind::UInt16:
741 case SimpleTypeKind::UInt16Short:
742 return lldb::eBasicTypeUnsignedShort;
743 case SimpleTypeKind::Int32Long:
744 return lldb::eBasicTypeLong;
745 case SimpleTypeKind::UInt32Long:
746 return lldb::eBasicTypeUnsignedLong;
747 case SimpleTypeKind::Void:
748 return lldb::eBasicTypeVoid;
749 case SimpleTypeKind::WideCharacter:
750 return lldb::eBasicTypeWChar;
752 return lldb::eBasicTypeInvalid;
756 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
758 case SimpleTypeKind::Boolean128:
759 case SimpleTypeKind::Int128:
760 case SimpleTypeKind::UInt128:
761 case SimpleTypeKind::Float128:
763 case SimpleTypeKind::Complex80:
764 case SimpleTypeKind::Float80:
766 case SimpleTypeKind::Boolean64:
767 case SimpleTypeKind::Complex64:
768 case SimpleTypeKind::UInt64:
769 case SimpleTypeKind::UInt64Quad:
770 case SimpleTypeKind::Float64:
771 case SimpleTypeKind::Int64:
772 case SimpleTypeKind::Int64Quad:
774 case SimpleTypeKind::Boolean32:
775 case SimpleTypeKind::Character32:
776 case SimpleTypeKind::Complex32:
777 case SimpleTypeKind::Float32:
778 case SimpleTypeKind::Int32:
779 case SimpleTypeKind::Int32Long:
780 case SimpleTypeKind::UInt32Long:
781 case SimpleTypeKind::HResult:
782 case SimpleTypeKind::UInt32:
784 case SimpleTypeKind::Boolean16:
785 case SimpleTypeKind::Character16:
786 case SimpleTypeKind::Float16:
787 case SimpleTypeKind::Int16:
788 case SimpleTypeKind::Int16Short:
789 case SimpleTypeKind::UInt16:
790 case SimpleTypeKind::UInt16Short:
791 case SimpleTypeKind::WideCharacter:
793 case SimpleTypeKind::Boolean8:
794 case SimpleTypeKind::Byte:
795 case SimpleTypeKind::UnsignedCharacter:
796 case SimpleTypeKind::NarrowCharacter:
797 case SimpleTypeKind::SignedCharacter:
798 case SimpleTypeKind::SByte:
800 case SimpleTypeKind::Void:
806 PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
808 if (id.index.isSimple())
811 CVType cvt = tpi.getType(id.index);
813 // Only tag records have a best and a worst record.
814 if (!IsTagRecord(cvt))
817 // Tag records that are not forward decls are full decls, hence they are the
819 if (!IsForwardRefUdt(cvt))
822 return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
825 template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
827 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
828 return record.getSize();
831 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
832 llvm::pdb::TpiStream &tpi) {
833 if (id.index.isSimple()) {
834 switch (id.index.getSimpleMode()) {
835 case SimpleTypeMode::Direct:
836 return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
837 case SimpleTypeMode::NearPointer32:
838 case SimpleTypeMode::FarPointer32:
840 case SimpleTypeMode::NearPointer64:
842 case SimpleTypeMode::NearPointer128:
850 TypeIndex index = id.index;
851 if (IsForwardRefUdt(index, tpi))
852 index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
854 CVType cvt = tpi.getType(index);
855 switch (cvt.kind()) {
857 return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
860 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
861 return GetSizeOfType({record.UnderlyingType}, tpi);
864 return GetSizeOfTypeInternal<PointerRecord>(cvt);
866 return GetSizeOfTypeInternal<ArrayRecord>(cvt);
870 return GetSizeOfTypeInternal<ClassRecord>(cvt);
872 return GetSizeOfTypeInternal<UnionRecord>(cvt);