xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- PdbUtil.cpp -------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PdbUtil.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "DWARFLocationExpression.h"
120b57cec5SDimitry Andric #include "PdbIndex.h"
130b57cec5SDimitry Andric #include "PdbSymUid.h"
140b57cec5SDimitry Andric 
1581ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
22bdd1243dSDimitry Andric #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
230b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
240b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
2581ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
260b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace lldb_private;
290b57cec5SDimitry Andric using namespace lldb_private::npdb;
300b57cec5SDimitry Andric using namespace llvm::codeview;
310b57cec5SDimitry Andric using namespace llvm::pdb;
320b57cec5SDimitry Andric 
33bdd1243dSDimitry Andric // The returned range list is guaranteed to be sorted and no overlaps between
34bdd1243dSDimitry Andric // adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
350b57cec5SDimitry Andric static Variable::RangeList
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)360b57cec5SDimitry Andric MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
370b57cec5SDimitry Andric               llvm::ArrayRef<LocalVariableAddrGap> gaps) {
380b57cec5SDimitry Andric   lldb::addr_t start =
390b57cec5SDimitry Andric       index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
4081ad6265SDimitry Andric   if (start == LLDB_INVALID_ADDRESS)
4181ad6265SDimitry Andric     return {};
420b57cec5SDimitry Andric   lldb::addr_t end = start + range.Range;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   Variable::RangeList result;
450b57cec5SDimitry Andric   while (!gaps.empty()) {
460b57cec5SDimitry Andric     const LocalVariableAddrGap &gap = gaps.front();
4781ad6265SDimitry Andric     lldb::addr_t gap_start = start + gap.GapStartOffset;
4881ad6265SDimitry Andric     result.Append(start, gap_start - start);
4981ad6265SDimitry Andric     start = gap_start + gap.Range;
500b57cec5SDimitry Andric     gaps = gaps.drop_front();
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   result.Append(start, end - start);
540b57cec5SDimitry Andric   return result;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
5781ad6265SDimitry Andric namespace {
58bdd1243dSDimitry Andric struct MemberLocations {
59bdd1243dSDimitry Andric   std::map<uint64_t, MemberValLocation> offset_to_location;
60bdd1243dSDimitry Andric   DWARFExpression expr;
61bdd1243dSDimitry Andric   bool is_dwarf = false;
62bdd1243dSDimitry Andric 
63bdd1243dSDimitry Andric   MemberLocations() = default;
MemberLocations__anon86ad4bd50111::MemberLocations64bdd1243dSDimitry Andric   MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
MemberLocations__anon86ad4bd50111::MemberLocations65bdd1243dSDimitry Andric   MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
66bdd1243dSDimitry Andric     insert(offset, member_loc);
67bdd1243dSDimitry Andric   }
68bdd1243dSDimitry Andric 
insert__anon86ad4bd50111::MemberLocations69bdd1243dSDimitry Andric   void insert(uint64_t offset, const MemberValLocation &member_loc) {
70bdd1243dSDimitry Andric     offset_to_location[offset] = member_loc;
71bdd1243dSDimitry Andric   }
72bdd1243dSDimitry Andric 
73bdd1243dSDimitry Andric   struct Comparator {
74bdd1243dSDimitry Andric   public:
operator ()__anon86ad4bd50111::MemberLocations::Comparator75bdd1243dSDimitry Andric     bool operator()(const MemberLocations &, const MemberLocations &) const {
76bdd1243dSDimitry Andric       return false;
7781ad6265SDimitry Andric     }
7881ad6265SDimitry Andric   };
79bdd1243dSDimitry Andric };
80bdd1243dSDimitry Andric 
81bdd1243dSDimitry Andric // A range map with address ranges to a map of pair of offset and locaitons.
82bdd1243dSDimitry Andric typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
83bdd1243dSDimitry Andric                         MemberLocations::Comparator>
84bdd1243dSDimitry Andric     RangeMap;
85bdd1243dSDimitry Andric 
AddMemberLocationRanges(RangeMap & location_map,uint64_t offset,MemberValLocation member_loc,const Variable::RangeList & ranges)86bdd1243dSDimitry Andric void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
87bdd1243dSDimitry Andric                              MemberValLocation member_loc,
88bdd1243dSDimitry Andric                              const Variable::RangeList &ranges) {
89bdd1243dSDimitry Andric   RangeMap new_location_map;
90bdd1243dSDimitry Andric   auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
91bdd1243dSDimitry Andric                                 RangeMap::Entry *entry) {
92bdd1243dSDimitry Andric     RangeMap::Entry overlap_region = {base, end - base, entry->data};
93bdd1243dSDimitry Andric     overlap_region.data.insert(offset, member_loc);
94bdd1243dSDimitry Andric     new_location_map.Append(overlap_region);
95bdd1243dSDimitry Andric   };
96bdd1243dSDimitry Andric 
97bdd1243dSDimitry Andric   for (const auto &range : ranges) {
98bdd1243dSDimitry Andric     lldb::addr_t base = range.GetRangeBase();
99bdd1243dSDimitry Andric     lldb::addr_t end = range.GetRangeEnd();
100bdd1243dSDimitry Andric     uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
101bdd1243dSDimitry Andric     while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
102bdd1243dSDimitry Andric       if (base >= end || entry->base >= end)
103bdd1243dSDimitry Andric         break;
104bdd1243dSDimitry Andric       if (entry->data.is_dwarf)
105bdd1243dSDimitry Andric         base = entry->GetRangeEnd();
106bdd1243dSDimitry Andric       else {
107bdd1243dSDimitry Andric         lldb::addr_t entry_end = entry->GetRangeEnd();
108bdd1243dSDimitry Andric         if (base > entry->base) {
109bdd1243dSDimitry Andric           if (end < entry_end)
110bdd1243dSDimitry Andric             new_location_map.Append({end, entry_end - end, entry->data});
111bdd1243dSDimitry Andric           add_overlap_region(base, end < entry_end ? end : entry_end, entry);
112bdd1243dSDimitry Andric           entry->SetRangeEnd(base);
113bdd1243dSDimitry Andric         } else if (base < entry->base) {
114bdd1243dSDimitry Andric           new_location_map.Append(
115bdd1243dSDimitry Andric               {base, entry->base - base, {offset, member_loc}});
116bdd1243dSDimitry Andric           if (entry_end == end)
117bdd1243dSDimitry Andric             entry->data.insert(offset, member_loc);
118bdd1243dSDimitry Andric           else {
119bdd1243dSDimitry Andric             add_overlap_region(entry->base, end, entry);
120bdd1243dSDimitry Andric             entry->ShrinkFront(end - entry->base);
121bdd1243dSDimitry Andric           }
122bdd1243dSDimitry Andric         } else {
123bdd1243dSDimitry Andric           if (end < entry_end) {
124bdd1243dSDimitry Andric             new_location_map.Append({end, entry_end, entry->data});
125bdd1243dSDimitry Andric             entry->SetRangeEnd(end);
126bdd1243dSDimitry Andric           }
127bdd1243dSDimitry Andric           entry->data.insert(offset, member_loc);
128bdd1243dSDimitry Andric         }
129bdd1243dSDimitry Andric         base = entry_end;
130bdd1243dSDimitry Andric       }
131bdd1243dSDimitry Andric       ++base_idx;
132bdd1243dSDimitry Andric     }
133bdd1243dSDimitry Andric     if (base >= end)
134bdd1243dSDimitry Andric       continue;
135bdd1243dSDimitry Andric     new_location_map.Append({base, end - base, {offset, member_loc}});
136bdd1243dSDimitry Andric   }
137bdd1243dSDimitry Andric   for (const auto &entry : new_location_map)
138bdd1243dSDimitry Andric     location_map.Append(entry);
139bdd1243dSDimitry Andric   if (!new_location_map.IsEmpty())
140bdd1243dSDimitry Andric     location_map.Sort();
141bdd1243dSDimitry Andric }
142bdd1243dSDimitry Andric 
AddDwarfRange(RangeMap & location_map,const DWARFExpression & expr,const Variable::RangeList & ranges)143bdd1243dSDimitry Andric void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
144bdd1243dSDimitry Andric                    const Variable::RangeList &ranges) {
145bdd1243dSDimitry Andric   if (!expr.IsValid())
146bdd1243dSDimitry Andric     return;
147bdd1243dSDimitry Andric   RangeMap new_location_map;
148bdd1243dSDimitry Andric   for (const auto &range : ranges) {
149bdd1243dSDimitry Andric     lldb::addr_t base = range.GetRangeBase();
150bdd1243dSDimitry Andric     lldb::addr_t end = range.GetRangeEnd();
151bdd1243dSDimitry Andric     uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
152bdd1243dSDimitry Andric     uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
153bdd1243dSDimitry Andric     // range is within an entry.
154bdd1243dSDimitry Andric     if (base_idx == end_idx && base_idx != UINT32_MAX) {
155bdd1243dSDimitry Andric       auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
156bdd1243dSDimitry Andric       if (base > entry->base) {
157bdd1243dSDimitry Andric         new_location_map.Append({entry->base, base - entry->base, entry->data});
158bdd1243dSDimitry Andric         entry->ShrinkFront(base - entry->base);
159bdd1243dSDimitry Andric       }
160bdd1243dSDimitry Andric       if (end == entry->GetRangeEnd())
161bdd1243dSDimitry Andric         entry->data = expr;
162bdd1243dSDimitry Andric       else {
163bdd1243dSDimitry Andric         entry->ShrinkFront(end - base);
164bdd1243dSDimitry Andric         new_location_map.Append({base, end - base, expr});
165bdd1243dSDimitry Andric       }
166bdd1243dSDimitry Andric       continue;
167bdd1243dSDimitry Andric     }
168bdd1243dSDimitry Andric     base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
169bdd1243dSDimitry Andric     if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
170bdd1243dSDimitry Andric       if (entry->Contains(base) && entry->base != base) {
171bdd1243dSDimitry Andric         entry->SetRangeEnd(base);
172bdd1243dSDimitry Andric         ++base_idx;
173bdd1243dSDimitry Andric       }
174bdd1243dSDimitry Andric     }
175bdd1243dSDimitry Andric     end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
176bdd1243dSDimitry Andric     if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
177bdd1243dSDimitry Andric       if (entry->Contains(end - 1)) {
178bdd1243dSDimitry Andric         if (entry->GetRangeEnd() == end)
179bdd1243dSDimitry Andric           ++end_idx;
180bdd1243dSDimitry Andric         else
181bdd1243dSDimitry Andric           entry->ShrinkFront(end - entry->base);
182bdd1243dSDimitry Andric       }
183bdd1243dSDimitry Andric     }
184bdd1243dSDimitry Andric 
185bdd1243dSDimitry Andric     if (end_idx == UINT32_MAX)
186bdd1243dSDimitry Andric       end_idx = location_map.GetSize();
187bdd1243dSDimitry Andric     // Erase existing ranges covered by new range.
188bdd1243dSDimitry Andric     location_map.Erase(base_idx, end_idx);
189bdd1243dSDimitry Andric     new_location_map.Append({base, end - base, expr});
190bdd1243dSDimitry Andric   }
191bdd1243dSDimitry Andric 
192bdd1243dSDimitry Andric   for (const auto &entry : new_location_map)
193bdd1243dSDimitry Andric     location_map.Append(entry);
194bdd1243dSDimitry Andric   location_map.Sort();
195bdd1243dSDimitry Andric }
19681ad6265SDimitry Andric } // namespace
19781ad6265SDimitry Andric 
create(CVType type)1980b57cec5SDimitry Andric CVTagRecord CVTagRecord::create(CVType type) {
1990b57cec5SDimitry Andric   assert(IsTagRecord(type) && "type is not a tag record!");
2000b57cec5SDimitry Andric   switch (type.kind()) {
2010b57cec5SDimitry Andric   case LF_CLASS:
2020b57cec5SDimitry Andric   case LF_STRUCTURE:
2030b57cec5SDimitry Andric   case LF_INTERFACE: {
2040b57cec5SDimitry Andric     ClassRecord cr;
2050b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
2060b57cec5SDimitry Andric     return CVTagRecord(std::move(cr));
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric   case LF_UNION: {
2090b57cec5SDimitry Andric     UnionRecord ur;
2100b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
2110b57cec5SDimitry Andric     return CVTagRecord(std::move(ur));
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric   case LF_ENUM: {
2140b57cec5SDimitry Andric     EnumRecord er;
2150b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
2160b57cec5SDimitry Andric     return CVTagRecord(std::move(er));
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric   default:
2190b57cec5SDimitry Andric     llvm_unreachable("Unreachable!");
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
CVTagRecord(ClassRecord && c)2230b57cec5SDimitry Andric CVTagRecord::CVTagRecord(ClassRecord &&c)
2240b57cec5SDimitry Andric     : cvclass(std::move(c)),
2250b57cec5SDimitry Andric       m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)2260b57cec5SDimitry Andric CVTagRecord::CVTagRecord(UnionRecord &&u)
2270b57cec5SDimitry Andric     : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)2280b57cec5SDimitry Andric CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
2290b57cec5SDimitry Andric 
CVSymToPDBSym(SymbolKind kind)2300b57cec5SDimitry Andric PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
2310b57cec5SDimitry Andric   switch (kind) {
2320b57cec5SDimitry Andric   case S_COMPILE3:
2330b57cec5SDimitry Andric   case S_OBJNAME:
2340b57cec5SDimitry Andric     return PDB_SymType::CompilandDetails;
2350b57cec5SDimitry Andric   case S_ENVBLOCK:
2360b57cec5SDimitry Andric     return PDB_SymType::CompilandEnv;
2370b57cec5SDimitry Andric   case S_THUNK32:
2380b57cec5SDimitry Andric   case S_TRAMPOLINE:
2390b57cec5SDimitry Andric     return PDB_SymType::Thunk;
2400b57cec5SDimitry Andric   case S_COFFGROUP:
2410b57cec5SDimitry Andric     return PDB_SymType::CoffGroup;
2420b57cec5SDimitry Andric   case S_EXPORT:
2430b57cec5SDimitry Andric     return PDB_SymType::Export;
2440b57cec5SDimitry Andric   case S_LPROC32:
2450b57cec5SDimitry Andric   case S_GPROC32:
2460b57cec5SDimitry Andric   case S_LPROC32_DPC:
2470b57cec5SDimitry Andric     return PDB_SymType::Function;
2480b57cec5SDimitry Andric   case S_PUB32:
2490b57cec5SDimitry Andric     return PDB_SymType::PublicSymbol;
2500b57cec5SDimitry Andric   case S_INLINESITE:
2510b57cec5SDimitry Andric     return PDB_SymType::InlineSite;
2520b57cec5SDimitry Andric   case S_LOCAL:
2530b57cec5SDimitry Andric   case S_BPREL32:
2540b57cec5SDimitry Andric   case S_REGREL32:
2550b57cec5SDimitry Andric   case S_MANCONSTANT:
2560b57cec5SDimitry Andric   case S_CONSTANT:
2570b57cec5SDimitry Andric   case S_LDATA32:
2580b57cec5SDimitry Andric   case S_GDATA32:
2590b57cec5SDimitry Andric   case S_LMANDATA:
2600b57cec5SDimitry Andric   case S_GMANDATA:
2610b57cec5SDimitry Andric   case S_LTHREAD32:
2620b57cec5SDimitry Andric   case S_GTHREAD32:
2630b57cec5SDimitry Andric     return PDB_SymType::Data;
2640b57cec5SDimitry Andric   case S_BLOCK32:
2650b57cec5SDimitry Andric     return PDB_SymType::Block;
2660b57cec5SDimitry Andric   case S_LABEL32:
2670b57cec5SDimitry Andric     return PDB_SymType::Label;
2680b57cec5SDimitry Andric   case S_CALLSITEINFO:
2690b57cec5SDimitry Andric     return PDB_SymType::CallSite;
2700b57cec5SDimitry Andric   case S_HEAPALLOCSITE:
2710b57cec5SDimitry Andric     return PDB_SymType::HeapAllocationSite;
2720b57cec5SDimitry Andric   case S_CALLEES:
2730b57cec5SDimitry Andric     return PDB_SymType::Callee;
2740b57cec5SDimitry Andric   case S_CALLERS:
2750b57cec5SDimitry Andric     return PDB_SymType::Caller;
2760b57cec5SDimitry Andric   default:
2770b57cec5SDimitry Andric     lldbassert(false && "Invalid symbol record kind!");
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric   return PDB_SymType::None;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
CVTypeToPDBType(TypeLeafKind kind)2820b57cec5SDimitry Andric PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
2830b57cec5SDimitry Andric   switch (kind) {
2840b57cec5SDimitry Andric   case LF_ARRAY:
2850b57cec5SDimitry Andric     return PDB_SymType::ArrayType;
2860b57cec5SDimitry Andric   case LF_ARGLIST:
2870b57cec5SDimitry Andric     return PDB_SymType::FunctionSig;
2880b57cec5SDimitry Andric   case LF_BCLASS:
2890b57cec5SDimitry Andric     return PDB_SymType::BaseClass;
2900b57cec5SDimitry Andric   case LF_BINTERFACE:
2910b57cec5SDimitry Andric     return PDB_SymType::BaseInterface;
2920b57cec5SDimitry Andric   case LF_CLASS:
2930b57cec5SDimitry Andric   case LF_STRUCTURE:
2940b57cec5SDimitry Andric   case LF_INTERFACE:
2950b57cec5SDimitry Andric   case LF_UNION:
2960b57cec5SDimitry Andric     return PDB_SymType::UDT;
2970b57cec5SDimitry Andric   case LF_POINTER:
2980b57cec5SDimitry Andric     return PDB_SymType::PointerType;
2990b57cec5SDimitry Andric   case LF_ENUM:
3000b57cec5SDimitry Andric     return PDB_SymType::Enum;
3010b57cec5SDimitry Andric   case LF_PROCEDURE:
3020b57cec5SDimitry Andric     return PDB_SymType::FunctionSig;
3030b57cec5SDimitry Andric   case LF_BITFIELD:
3040b57cec5SDimitry Andric     return PDB_SymType::BuiltinType;
3050b57cec5SDimitry Andric   default:
3060b57cec5SDimitry Andric     lldbassert(false && "Invalid type record kind!");
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric   return PDB_SymType::None;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric 
SymbolHasAddress(const CVSymbol & sym)3110b57cec5SDimitry Andric bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
3120b57cec5SDimitry Andric   switch (sym.kind()) {
3130b57cec5SDimitry Andric   case S_GPROC32:
3140b57cec5SDimitry Andric   case S_LPROC32:
3150b57cec5SDimitry Andric   case S_GPROC32_ID:
3160b57cec5SDimitry Andric   case S_LPROC32_ID:
3170b57cec5SDimitry Andric   case S_LPROC32_DPC:
3180b57cec5SDimitry Andric   case S_LPROC32_DPC_ID:
3190b57cec5SDimitry Andric   case S_THUNK32:
3200b57cec5SDimitry Andric   case S_TRAMPOLINE:
3210b57cec5SDimitry Andric   case S_COFFGROUP:
3220b57cec5SDimitry Andric   case S_BLOCK32:
3230b57cec5SDimitry Andric   case S_LABEL32:
3240b57cec5SDimitry Andric   case S_CALLSITEINFO:
3250b57cec5SDimitry Andric   case S_HEAPALLOCSITE:
3260b57cec5SDimitry Andric   case S_LDATA32:
3270b57cec5SDimitry Andric   case S_GDATA32:
3280b57cec5SDimitry Andric   case S_LMANDATA:
3290b57cec5SDimitry Andric   case S_GMANDATA:
3300b57cec5SDimitry Andric   case S_LTHREAD32:
3310b57cec5SDimitry Andric   case S_GTHREAD32:
3320b57cec5SDimitry Andric     return true;
3330b57cec5SDimitry Andric   default:
3340b57cec5SDimitry Andric     return false;
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric 
SymbolIsCode(const CVSymbol & sym)3380b57cec5SDimitry Andric bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
3390b57cec5SDimitry Andric   switch (sym.kind()) {
3400b57cec5SDimitry Andric   case S_GPROC32:
3410b57cec5SDimitry Andric   case S_LPROC32:
3420b57cec5SDimitry Andric   case S_GPROC32_ID:
3430b57cec5SDimitry Andric   case S_LPROC32_ID:
3440b57cec5SDimitry Andric   case S_LPROC32_DPC:
3450b57cec5SDimitry Andric   case S_LPROC32_DPC_ID:
3460b57cec5SDimitry Andric   case S_THUNK32:
3470b57cec5SDimitry Andric   case S_TRAMPOLINE:
3480b57cec5SDimitry Andric   case S_COFFGROUP:
3490b57cec5SDimitry Andric   case S_BLOCK32:
3500b57cec5SDimitry Andric     return true;
3510b57cec5SDimitry Andric   default:
3520b57cec5SDimitry Andric     return false;
3530b57cec5SDimitry Andric   }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
createRecord(const CVSymbol & sym)3560b57cec5SDimitry Andric template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
3570b57cec5SDimitry Andric   RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
3580b57cec5SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
3590b57cec5SDimitry Andric   return record;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric template <typename RecordT>
GetSegmentAndOffset(const CVSymbol & sym)3630b57cec5SDimitry Andric static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
3640b57cec5SDimitry Andric   RecordT record = createRecord<RecordT>(sym);
3650b57cec5SDimitry Andric   return {record.Segment, record.CodeOffset};
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric template <>
GetSegmentAndOffset(const CVSymbol & sym)3690b57cec5SDimitry Andric SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
3700b57cec5SDimitry Andric   TrampolineSym record = createRecord<TrampolineSym>(sym);
3710b57cec5SDimitry Andric   return {record.ThunkSection, record.ThunkOffset};
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
GetSegmentAndOffset(const CVSymbol & sym)3740b57cec5SDimitry Andric template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
3750b57cec5SDimitry Andric   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
3760b57cec5SDimitry Andric   return {record.Segment, record.Offset};
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric template <>
GetSegmentAndOffset(const CVSymbol & sym)3800b57cec5SDimitry Andric SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
3810b57cec5SDimitry Andric   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
3820b57cec5SDimitry Andric   return {record.Segment, record.Offset};
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
GetSegmentAndOffset(const CVSymbol & sym)3850b57cec5SDimitry Andric template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
3860b57cec5SDimitry Andric   DataSym record = createRecord<DataSym>(sym);
3870b57cec5SDimitry Andric   return {record.Segment, record.DataOffset};
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric template <>
GetSegmentAndOffset(const CVSymbol & sym)3910b57cec5SDimitry Andric SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
3920b57cec5SDimitry Andric   ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
3930b57cec5SDimitry Andric   return {record.Segment, record.DataOffset};
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
GetSegmentAndOffset(const CVSymbol & sym)3960b57cec5SDimitry Andric SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
3970b57cec5SDimitry Andric   switch (sym.kind()) {
3980b57cec5SDimitry Andric   case S_GPROC32:
3990b57cec5SDimitry Andric   case S_LPROC32:
4000b57cec5SDimitry Andric   case S_GPROC32_ID:
4010b57cec5SDimitry Andric   case S_LPROC32_ID:
4020b57cec5SDimitry Andric   case S_LPROC32_DPC:
4030b57cec5SDimitry Andric   case S_LPROC32_DPC_ID:
4040b57cec5SDimitry Andric     return ::GetSegmentAndOffset<ProcSym>(sym);
4050b57cec5SDimitry Andric   case S_THUNK32:
4060b57cec5SDimitry Andric     return ::GetSegmentAndOffset<Thunk32Sym>(sym);
4070b57cec5SDimitry Andric     break;
4080b57cec5SDimitry Andric   case S_TRAMPOLINE:
4090b57cec5SDimitry Andric     return ::GetSegmentAndOffset<TrampolineSym>(sym);
4100b57cec5SDimitry Andric     break;
4110b57cec5SDimitry Andric   case S_COFFGROUP:
4120b57cec5SDimitry Andric     return ::GetSegmentAndOffset<CoffGroupSym>(sym);
4130b57cec5SDimitry Andric     break;
4140b57cec5SDimitry Andric   case S_BLOCK32:
4150b57cec5SDimitry Andric     return ::GetSegmentAndOffset<BlockSym>(sym);
4160b57cec5SDimitry Andric     break;
4170b57cec5SDimitry Andric   case S_LABEL32:
4180b57cec5SDimitry Andric     return ::GetSegmentAndOffset<LabelSym>(sym);
4190b57cec5SDimitry Andric     break;
4200b57cec5SDimitry Andric   case S_CALLSITEINFO:
4210b57cec5SDimitry Andric     return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
4220b57cec5SDimitry Andric     break;
4230b57cec5SDimitry Andric   case S_HEAPALLOCSITE:
4240b57cec5SDimitry Andric     return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
4250b57cec5SDimitry Andric     break;
4260b57cec5SDimitry Andric   case S_LDATA32:
4270b57cec5SDimitry Andric   case S_GDATA32:
4280b57cec5SDimitry Andric   case S_LMANDATA:
4290b57cec5SDimitry Andric   case S_GMANDATA:
4300b57cec5SDimitry Andric     return ::GetSegmentAndOffset<DataSym>(sym);
4310b57cec5SDimitry Andric     break;
4320b57cec5SDimitry Andric   case S_LTHREAD32:
4330b57cec5SDimitry Andric   case S_GTHREAD32:
4340b57cec5SDimitry Andric     return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
4350b57cec5SDimitry Andric     break;
4360b57cec5SDimitry Andric   default:
4370b57cec5SDimitry Andric     lldbassert(false && "Record does not have a segment/offset!");
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric   return {0, 0};
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric template <typename RecordT>
GetSegmentOffsetAndLength(const CVSymbol & sym)4430b57cec5SDimitry Andric SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
4440b57cec5SDimitry Andric   RecordT record = createRecord<RecordT>(sym);
4450b57cec5SDimitry Andric   return {record.Segment, record.CodeOffset, record.CodeSize};
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric template <>
4490b57cec5SDimitry Andric SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)4500b57cec5SDimitry Andric GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
4510b57cec5SDimitry Andric   TrampolineSym record = createRecord<TrampolineSym>(sym);
4520b57cec5SDimitry Andric   return {record.ThunkSection, record.ThunkOffset, record.Size};
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)4560b57cec5SDimitry Andric SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
4570b57cec5SDimitry Andric   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
4580b57cec5SDimitry Andric   return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric template <>
4620b57cec5SDimitry Andric SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)4630b57cec5SDimitry Andric GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
4640b57cec5SDimitry Andric   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
4650b57cec5SDimitry Andric   return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)4690b57cec5SDimitry Andric lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
4700b57cec5SDimitry Andric   switch (sym.kind()) {
4710b57cec5SDimitry Andric   case S_GPROC32:
4720b57cec5SDimitry Andric   case S_LPROC32:
4730b57cec5SDimitry Andric   case S_GPROC32_ID:
4740b57cec5SDimitry Andric   case S_LPROC32_ID:
4750b57cec5SDimitry Andric   case S_LPROC32_DPC:
4760b57cec5SDimitry Andric   case S_LPROC32_DPC_ID:
4770b57cec5SDimitry Andric     return ::GetSegmentOffsetAndLength<ProcSym>(sym);
4780b57cec5SDimitry Andric   case S_THUNK32:
4790b57cec5SDimitry Andric     return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
4800b57cec5SDimitry Andric     break;
4810b57cec5SDimitry Andric   case S_TRAMPOLINE:
4820b57cec5SDimitry Andric     return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
4830b57cec5SDimitry Andric     break;
4840b57cec5SDimitry Andric   case S_COFFGROUP:
4850b57cec5SDimitry Andric     return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
4860b57cec5SDimitry Andric     break;
4870b57cec5SDimitry Andric   case S_BLOCK32:
4880b57cec5SDimitry Andric     return ::GetSegmentOffsetAndLength<BlockSym>(sym);
4890b57cec5SDimitry Andric     break;
4900b57cec5SDimitry Andric   default:
4910b57cec5SDimitry Andric     lldbassert(false && "Record does not have a segment/offset/length triple!");
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric   return {0, 0, 0};
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
IsForwardRefUdt(CVType cvt)4960b57cec5SDimitry Andric bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
4970b57cec5SDimitry Andric   ClassRecord cr;
4980b57cec5SDimitry Andric   UnionRecord ur;
4990b57cec5SDimitry Andric   EnumRecord er;
5000b57cec5SDimitry Andric   switch (cvt.kind()) {
5010b57cec5SDimitry Andric   case LF_CLASS:
5020b57cec5SDimitry Andric   case LF_STRUCTURE:
5030b57cec5SDimitry Andric   case LF_INTERFACE:
5040b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
5050b57cec5SDimitry Andric     return cr.isForwardRef();
5060b57cec5SDimitry Andric   case LF_UNION:
5070b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
5080b57cec5SDimitry Andric     return ur.isForwardRef();
5090b57cec5SDimitry Andric   case LF_ENUM:
5100b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
5110b57cec5SDimitry Andric     return er.isForwardRef();
5120b57cec5SDimitry Andric   default:
5130b57cec5SDimitry Andric     return false;
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
IsTagRecord(llvm::codeview::CVType cvt)5170b57cec5SDimitry Andric bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
5180b57cec5SDimitry Andric   switch (cvt.kind()) {
5190b57cec5SDimitry Andric   case LF_CLASS:
5200b57cec5SDimitry Andric   case LF_STRUCTURE:
5210b57cec5SDimitry Andric   case LF_UNION:
5220b57cec5SDimitry Andric   case LF_ENUM:
5230b57cec5SDimitry Andric     return true;
5240b57cec5SDimitry Andric   default:
5250b57cec5SDimitry Andric     return false;
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric 
IsClassStructUnion(llvm::codeview::CVType cvt)5290b57cec5SDimitry Andric bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
5300b57cec5SDimitry Andric   switch (cvt.kind()) {
5310b57cec5SDimitry Andric   case LF_CLASS:
5320b57cec5SDimitry Andric   case LF_STRUCTURE:
5330b57cec5SDimitry Andric   case LF_UNION:
5340b57cec5SDimitry Andric     return true;
5350b57cec5SDimitry Andric   default:
5360b57cec5SDimitry Andric     return false;
5370b57cec5SDimitry Andric   }
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)5400b57cec5SDimitry Andric bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
5410b57cec5SDimitry Andric                                          TpiStream &tpi) {
5420b57cec5SDimitry Andric   if (id.is_ipi || id.index.isSimple())
5430b57cec5SDimitry Andric     return false;
5440b57cec5SDimitry Andric   return IsForwardRefUdt(tpi.getType(id.index));
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric 
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)5470b57cec5SDimitry Andric bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
5480b57cec5SDimitry Andric   if (id.is_ipi || id.index.isSimple())
5490b57cec5SDimitry Andric     return false;
5500b57cec5SDimitry Andric   return IsTagRecord(tpi.getType(id.index));
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric lldb::AccessType
TranslateMemberAccess(MemberAccess access)5540b57cec5SDimitry Andric lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
5550b57cec5SDimitry Andric   switch (access) {
5560b57cec5SDimitry Andric   case MemberAccess::Private:
5570b57cec5SDimitry Andric     return lldb::eAccessPrivate;
5580b57cec5SDimitry Andric   case MemberAccess::Protected:
5590b57cec5SDimitry Andric     return lldb::eAccessProtected;
5600b57cec5SDimitry Andric   case MemberAccess::Public:
5610b57cec5SDimitry Andric     return lldb::eAccessPublic;
5620b57cec5SDimitry Andric   case MemberAccess::None:
5630b57cec5SDimitry Andric     return lldb::eAccessNone;
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric   llvm_unreachable("unreachable");
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric 
GetFieldListIndex(CVType cvt)5680b57cec5SDimitry Andric TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
5690b57cec5SDimitry Andric   switch (cvt.kind()) {
5700b57cec5SDimitry Andric   case LF_CLASS:
5710b57cec5SDimitry Andric   case LF_STRUCTURE:
5720b57cec5SDimitry Andric   case LF_INTERFACE: {
5730b57cec5SDimitry Andric     ClassRecord cr;
5740b57cec5SDimitry Andric     cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
5750b57cec5SDimitry Andric     return cr.FieldList;
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric   case LF_UNION: {
5780b57cec5SDimitry Andric     UnionRecord ur;
5790b57cec5SDimitry Andric     cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
5800b57cec5SDimitry Andric     return ur.FieldList;
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric   case LF_ENUM: {
5830b57cec5SDimitry Andric     EnumRecord er;
5840b57cec5SDimitry Andric     cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
5850b57cec5SDimitry Andric     return er.FieldList;
5860b57cec5SDimitry Andric   }
5870b57cec5SDimitry Andric   default:
5880b57cec5SDimitry Andric     llvm_unreachable("Unreachable!");
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric 
LookThroughModifierRecord(CVType modifier)5920b57cec5SDimitry Andric TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
5930b57cec5SDimitry Andric   lldbassert(modifier.kind() == LF_MODIFIER);
5940b57cec5SDimitry Andric   ModifierRecord mr;
5950b57cec5SDimitry Andric   llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
5960b57cec5SDimitry Andric   return mr.ModifiedType;
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric 
DropNameScope(llvm::StringRef name)5990b57cec5SDimitry Andric llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
6000b57cec5SDimitry Andric   return MSVCUndecoratedNameParser::DropScope(name);
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
GetVariableNameInfo(CVSymbol sym)6030b57cec5SDimitry Andric VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
604972a253aSDimitry Andric   VariableInfo result = {};
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   if (sym.kind() == S_REGREL32) {
6070b57cec5SDimitry Andric     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
6080b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
6090b57cec5SDimitry Andric     result.type = reg.Type;
6100b57cec5SDimitry Andric     result.name = reg.Name;
6110b57cec5SDimitry Andric     return result;
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   if (sym.kind() == S_REGISTER) {
6150b57cec5SDimitry Andric     RegisterSym reg(SymbolRecordKind::RegisterSym);
6160b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
6170b57cec5SDimitry Andric     result.type = reg.Index;
6180b57cec5SDimitry Andric     result.name = reg.Name;
6190b57cec5SDimitry Andric     return result;
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   if (sym.kind() == S_LOCAL) {
6230b57cec5SDimitry Andric     LocalSym local(SymbolRecordKind::LocalSym);
6240b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
6250b57cec5SDimitry Andric     result.type = local.Type;
6260b57cec5SDimitry Andric     result.name = local.Name;
62781ad6265SDimitry Andric     result.is_param =
62881ad6265SDimitry Andric         ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
6290b57cec5SDimitry Andric     return result;
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
6330b57cec5SDimitry Andric     DataSym data(SymbolRecordKind::DataSym);
6340b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
6350b57cec5SDimitry Andric     result.type = data.Type;
6360b57cec5SDimitry Andric     result.name = data.Name;
6370b57cec5SDimitry Andric     return result;
6380b57cec5SDimitry Andric   }
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
6410b57cec5SDimitry Andric     ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
6420b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
6430b57cec5SDimitry Andric     result.type = data.Type;
6440b57cec5SDimitry Andric     result.name = data.Name;
6450b57cec5SDimitry Andric     return result;
6460b57cec5SDimitry Andric   }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   if (sym.kind() == S_CONSTANT) {
6490b57cec5SDimitry Andric     ConstantSym constant(SymbolRecordKind::ConstantSym);
6500b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
6510b57cec5SDimitry Andric     result.type = constant.Type;
6520b57cec5SDimitry Andric     result.name = constant.Name;
6530b57cec5SDimitry Andric     return result;
6540b57cec5SDimitry Andric   }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   lldbassert(false && "Invalid variable record kind!");
6570b57cec5SDimitry Andric   return {};
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric static llvm::FixedStreamArray<FrameData>::Iterator
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)6610b57cec5SDimitry Andric GetCorrespondingFrameData(lldb::addr_t load_addr,
6620b57cec5SDimitry Andric                           const DebugFrameDataSubsectionRef &fpo_data,
6630b57cec5SDimitry Andric                           const Variable::RangeList &ranges) {
6640b57cec5SDimitry Andric   lldbassert(!ranges.IsEmpty());
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   // assume that all variable ranges correspond to one frame data
6670b57cec5SDimitry Andric   using RangeListEntry = Variable::RangeList::Entry;
6680b57cec5SDimitry Andric   const RangeListEntry &range = ranges.GetEntryRef(0);
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   auto it = fpo_data.begin();
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   // start by searching first frame data range containing variable range
6730b57cec5SDimitry Andric   for (; it != fpo_data.end(); ++it) {
6740b57cec5SDimitry Andric     RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     if (fd_range.Contains(range)) {
6770b57cec5SDimitry Andric       break;
6780b57cec5SDimitry Andric     }
6790b57cec5SDimitry Andric   }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   // then first most nested entry that still contains variable range
6820b57cec5SDimitry Andric   auto found = it;
6830b57cec5SDimitry Andric   for (; it != fpo_data.end(); ++it) {
6840b57cec5SDimitry Andric     RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric     if (!fd_range.Contains(range)) {
6870b57cec5SDimitry Andric       break;
6880b57cec5SDimitry Andric     }
6890b57cec5SDimitry Andric     found = it;
6900b57cec5SDimitry Andric   }
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric   return found;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)6950b57cec5SDimitry Andric static bool GetFrameDataProgram(PdbIndex &index,
6960b57cec5SDimitry Andric                                 const Variable::RangeList &ranges,
6970b57cec5SDimitry Andric                                 llvm::StringRef &out_program) {
6980b57cec5SDimitry Andric   const DebugFrameDataSubsectionRef &new_fpo_data =
6990b57cec5SDimitry Andric       index.dbi().getNewFpoRecords();
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric   auto frame_data_it =
7020b57cec5SDimitry Andric       GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
7030b57cec5SDimitry Andric   if (frame_data_it == new_fpo_data.end())
7040b57cec5SDimitry Andric     return false;
7050b57cec5SDimitry Andric 
706*06c3fb27SDimitry Andric   auto strings = index.pdb().getStringTable();
707*06c3fb27SDimitry Andric   if (!strings) {
708*06c3fb27SDimitry Andric     consumeError(strings.takeError());
709*06c3fb27SDimitry Andric     return false;
710*06c3fb27SDimitry Andric   }
711*06c3fb27SDimitry Andric   out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));
7120b57cec5SDimitry Andric   return true;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric 
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)7150b57cec5SDimitry Andric static RegisterId GetBaseFrameRegister(PdbIndex &index,
7160b57cec5SDimitry Andric                                        PdbCompilandSymId frame_proc_id,
7170b57cec5SDimitry Andric                                        bool is_parameter) {
7180b57cec5SDimitry Andric   CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
71981ad6265SDimitry Andric   if (frame_proc_cvs.kind() != S_FRAMEPROC)
72081ad6265SDimitry Andric     return RegisterId::NONE;
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
7230b57cec5SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
7240b57cec5SDimitry Andric                                                            frame_proc));
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   CPUType cpu_type = index.compilands()
7270b57cec5SDimitry Andric                          .GetCompiland(frame_proc_id.modi)
7280b57cec5SDimitry Andric                          ->m_compile_opts->Machine;
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
7310b57cec5SDimitry Andric                       : frame_proc.getLocalFramePtrReg(cpu_type);
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric 
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & func_block,lldb::ModuleSP module)7340b57cec5SDimitry Andric VariableInfo lldb_private::npdb::GetVariableLocationInfo(
735753f127fSDimitry Andric     PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
7360b57cec5SDimitry Andric     lldb::ModuleSP module) {
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   CVSymbol sym = index.ReadSymbolRecord(var_id);
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   VariableInfo result = GetVariableNameInfo(sym);
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric   if (sym.kind() == S_REGREL32) {
7430b57cec5SDimitry Andric     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
7440b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
745bdd1243dSDimitry Andric     result.location = DWARFExpressionList(
746bdd1243dSDimitry Andric         module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
747bdd1243dSDimitry Andric         nullptr);
7480b57cec5SDimitry Andric     return result;
7490b57cec5SDimitry Andric   }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   if (sym.kind() == S_REGISTER) {
7520b57cec5SDimitry Andric     RegisterSym reg(SymbolRecordKind::RegisterSym);
7530b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
754bdd1243dSDimitry Andric     result.location = DWARFExpressionList(
755bdd1243dSDimitry Andric         module, MakeEnregisteredLocationExpression(reg.Register, module),
756bdd1243dSDimitry Andric         nullptr);
7570b57cec5SDimitry Andric     return result;
7580b57cec5SDimitry Andric   }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   if (sym.kind() == S_LOCAL) {
7610b57cec5SDimitry Andric     LocalSym local(SymbolRecordKind::LocalSym);
762bdd1243dSDimitry Andric     if (llvm::Error error =
763bdd1243dSDimitry Andric             SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
764bdd1243dSDimitry Andric       llvm::consumeError(std::move(error));
765bdd1243dSDimitry Andric       return result;
766bdd1243dSDimitry Andric     }
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric     PdbCompilandSymId loc_specifier_id(var_id.modi,
7690b57cec5SDimitry Andric                                        var_id.offset + sym.RecordData.size());
770bdd1243dSDimitry Andric     CVSymbol loc_specifier_cvs;
771bdd1243dSDimitry Andric     // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
772bdd1243dSDimitry Andric     RegisterId base_reg = RegisterId::NONE;
773bdd1243dSDimitry Andric     size_t type_size = GetSizeOfType(result.type, index.tpi());
774bdd1243dSDimitry Andric     // A map from offset of a field in parent to size of the field.
775bdd1243dSDimitry Andric     std::map<uint64_t, size_t> offset_to_size;
776bdd1243dSDimitry Andric 
777bdd1243dSDimitry Andric     // When overlaps happens, always prefer the one that doesn't split the value
778bdd1243dSDimitry Andric     // into multiple locations and the location parsed first is perfered.
779bdd1243dSDimitry Andric     RangeMap location_map;
780bdd1243dSDimitry Andric 
781bdd1243dSDimitry Andric     // Iterate through all location records after S_LOCAL. They describe the
782bdd1243dSDimitry Andric     // value of this variable at different locations.
783bdd1243dSDimitry Andric     bool finished = false;
784bdd1243dSDimitry Andric     while (!finished) {
785bdd1243dSDimitry Andric       loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
78681ad6265SDimitry Andric       switch (loc_specifier_cvs.kind()) {
78781ad6265SDimitry Andric       case S_DEFRANGE_FRAMEPOINTER_REL: {
7880b57cec5SDimitry Andric         DefRangeFramePointerRelSym loc(
7890b57cec5SDimitry Andric             SymbolRecordKind::DefRangeFramePointerRelSym);
790bdd1243dSDimitry Andric         if (llvm::Error error =
791bdd1243dSDimitry Andric                 SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
792bdd1243dSDimitry Andric                     loc_specifier_cvs, loc)) {
793bdd1243dSDimitry Andric           llvm::consumeError(std::move(error));
794bdd1243dSDimitry Andric           return result;
795bdd1243dSDimitry Andric         }
796bdd1243dSDimitry Andric         Variable::RangeList raw_ranges =
797bdd1243dSDimitry Andric             MakeRangeList(index, loc.Range, loc.Gaps);
798bdd1243dSDimitry Andric         if (base_reg == RegisterId::NONE) {
7990b57cec5SDimitry Andric           PdbCompilandSymId func_scope_id =
800753f127fSDimitry Andric               PdbSymUid(func_block.GetID()).asCompilandSym();
8010b57cec5SDimitry Andric           CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
8020b57cec5SDimitry Andric           lldbassert(func_block_cvs.kind() == S_GPROC32 ||
8030b57cec5SDimitry Andric                      func_block_cvs.kind() == S_LPROC32);
804bdd1243dSDimitry Andric           PdbCompilandSymId frame_proc_id(func_scope_id.modi,
805bdd1243dSDimitry Andric                                           func_scope_id.offset +
806bdd1243dSDimitry Andric                                               func_block_cvs.length());
807bdd1243dSDimitry Andric           base_reg =
80881ad6265SDimitry Andric               GetBaseFrameRegister(index, frame_proc_id, result.is_param);
80981ad6265SDimitry Andric           if (base_reg == RegisterId::NONE)
81081ad6265SDimitry Andric             break;
811bdd1243dSDimitry Andric         }
812bdd1243dSDimitry Andric         DWARFExpression expr;
8130b57cec5SDimitry Andric         if (base_reg == RegisterId::VFRAME) {
8140b57cec5SDimitry Andric           llvm::StringRef program;
815bdd1243dSDimitry Andric           if (GetFrameDataProgram(index, raw_ranges, program))
816bdd1243dSDimitry Andric             expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
817bdd1243dSDimitry Andric                                                    module);
818bdd1243dSDimitry Andric           else {
8190b57cec5SDimitry Andric             // invalid variable
8200b57cec5SDimitry Andric           }
821bdd1243dSDimitry Andric         } else
822bdd1243dSDimitry Andric           expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
823bdd1243dSDimitry Andric         AddDwarfRange(location_map, expr, raw_ranges);
82481ad6265SDimitry Andric         break;
82581ad6265SDimitry Andric       }
82681ad6265SDimitry Andric       case S_DEFRANGE_REGISTER: {
82781ad6265SDimitry Andric         DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
828bdd1243dSDimitry Andric         if (llvm::Error error =
829bdd1243dSDimitry Andric                 SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
830bdd1243dSDimitry Andric                     loc_specifier_cvs, loc)) {
831bdd1243dSDimitry Andric           llvm::consumeError(std::move(error));
832bdd1243dSDimitry Andric           return result;
833bdd1243dSDimitry Andric         }
834bdd1243dSDimitry Andric         RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
835bdd1243dSDimitry Andric         Variable::RangeList raw_ranges =
836bdd1243dSDimitry Andric             MakeRangeList(index, loc.Range, loc.Gaps);
837bdd1243dSDimitry Andric         DWARFExpression expr =
838bdd1243dSDimitry Andric             MakeEnregisteredLocationExpression(reg_id, module);
839bdd1243dSDimitry Andric         AddDwarfRange(location_map, expr, raw_ranges);
840bdd1243dSDimitry Andric         break;
841bdd1243dSDimitry Andric       }
842bdd1243dSDimitry Andric       case S_DEFRANGE_REGISTER_REL: {
843bdd1243dSDimitry Andric         DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
844bdd1243dSDimitry Andric         if (llvm::Error error =
845bdd1243dSDimitry Andric                 SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
846bdd1243dSDimitry Andric                     loc_specifier_cvs, loc)) {
847bdd1243dSDimitry Andric           llvm::consumeError(std::move(error));
848bdd1243dSDimitry Andric           return result;
849bdd1243dSDimitry Andric         }
850bdd1243dSDimitry Andric         Variable::RangeList raw_ranges =
851bdd1243dSDimitry Andric             MakeRangeList(index, loc.Range, loc.Gaps);
852bdd1243dSDimitry Andric         RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
853bdd1243dSDimitry Andric         DWARFExpression expr;
854bdd1243dSDimitry Andric         if (reg_id == RegisterId::VFRAME) {
855bdd1243dSDimitry Andric           llvm::StringRef program;
856bdd1243dSDimitry Andric           if (GetFrameDataProgram(index, raw_ranges, program))
857bdd1243dSDimitry Andric             expr = MakeVFrameRelLocationExpression(
858bdd1243dSDimitry Andric                 program, loc.Hdr.BasePointerOffset, module);
859bdd1243dSDimitry Andric           else {
860bdd1243dSDimitry Andric             // invalid variable
861bdd1243dSDimitry Andric           }
862bdd1243dSDimitry Andric         } else {
863bdd1243dSDimitry Andric           expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
864bdd1243dSDimitry Andric                                               module);
865bdd1243dSDimitry Andric         }
866bdd1243dSDimitry Andric         // FIXME: If it's UDT, we need to know the size of the value in byte.
867bdd1243dSDimitry Andric         if (!loc.hasSpilledUDTMember())
868bdd1243dSDimitry Andric           AddDwarfRange(location_map, expr, raw_ranges);
86981ad6265SDimitry Andric         break;
87081ad6265SDimitry Andric       }
87181ad6265SDimitry Andric       case S_DEFRANGE_SUBFIELD_REGISTER: {
87281ad6265SDimitry Andric         DefRangeSubfieldRegisterSym loc(
87381ad6265SDimitry Andric             SymbolRecordKind::DefRangeSubfieldRegisterSym);
874bdd1243dSDimitry Andric         if (llvm::Error error =
875bdd1243dSDimitry Andric                 SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
876bdd1243dSDimitry Andric                     loc_specifier_cvs, loc)) {
877bdd1243dSDimitry Andric           llvm::consumeError(std::move(error));
87881ad6265SDimitry Andric           return result;
87981ad6265SDimitry Andric         }
880bdd1243dSDimitry Andric 
881bdd1243dSDimitry Andric         Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
882bdd1243dSDimitry Andric         uint32_t reg_size =
883bdd1243dSDimitry Andric             GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);
884bdd1243dSDimitry Andric         if (reg_size == 0)
885bdd1243dSDimitry Andric           break;
886bdd1243dSDimitry Andric         offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
887bdd1243dSDimitry Andric         AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
888bdd1243dSDimitry Andric                                 {loc.Hdr.Register, 0, true}, ranges);
889bdd1243dSDimitry Andric         break;
89081ad6265SDimitry Andric       }
891bdd1243dSDimitry Andric       // FIXME: Handle other kinds. LLVM only generates the 4 types of records
892bdd1243dSDimitry Andric       // above. MSVC generates other location types.
893bdd1243dSDimitry Andric       case S_DEFRANGE:
894bdd1243dSDimitry Andric       case S_DEFRANGE_SUBFIELD:
895bdd1243dSDimitry Andric       case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
896bdd1243dSDimitry Andric         break;
897bdd1243dSDimitry Andric       default:
898bdd1243dSDimitry Andric         finished = true;
899bdd1243dSDimitry Andric         break;
90081ad6265SDimitry Andric       }
90181ad6265SDimitry Andric       loc_specifier_id = PdbCompilandSymId(
90281ad6265SDimitry Andric           loc_specifier_id.modi,
90381ad6265SDimitry Andric           loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
90481ad6265SDimitry Andric     }
905bdd1243dSDimitry Andric     for (const auto &entry : location_map) {
906bdd1243dSDimitry Andric       DWARFExpression dwarf_expr =
907bdd1243dSDimitry Andric           entry.data.is_dwarf ? entry.data.expr
908bdd1243dSDimitry Andric                               : MakeEnregisteredLocationExpressionForComposite(
909bdd1243dSDimitry Andric                                     entry.data.offset_to_location,
910bdd1243dSDimitry Andric                                     offset_to_size, type_size, module);
911bdd1243dSDimitry Andric 
912bdd1243dSDimitry Andric       result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
913bdd1243dSDimitry Andric                                      dwarf_expr);
91481ad6265SDimitry Andric     }
9150b57cec5SDimitry Andric     return result;
9160b57cec5SDimitry Andric   }
9170b57cec5SDimitry Andric   llvm_unreachable("Symbol is not a local variable!");
9180b57cec5SDimitry Andric   return result;
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric lldb::BasicType
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)9220b57cec5SDimitry Andric lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
9230b57cec5SDimitry Andric   switch (kind) {
9240b57cec5SDimitry Andric   case SimpleTypeKind::Boolean128:
9250b57cec5SDimitry Andric   case SimpleTypeKind::Boolean16:
9260b57cec5SDimitry Andric   case SimpleTypeKind::Boolean32:
9270b57cec5SDimitry Andric   case SimpleTypeKind::Boolean64:
9280b57cec5SDimitry Andric   case SimpleTypeKind::Boolean8:
9290b57cec5SDimitry Andric     return lldb::eBasicTypeBool;
9300b57cec5SDimitry Andric   case SimpleTypeKind::Byte:
9310b57cec5SDimitry Andric   case SimpleTypeKind::UnsignedCharacter:
9320b57cec5SDimitry Andric     return lldb::eBasicTypeUnsignedChar;
9330b57cec5SDimitry Andric   case SimpleTypeKind::NarrowCharacter:
9340b57cec5SDimitry Andric     return lldb::eBasicTypeChar;
9350b57cec5SDimitry Andric   case SimpleTypeKind::SignedCharacter:
9360b57cec5SDimitry Andric   case SimpleTypeKind::SByte:
9370b57cec5SDimitry Andric     return lldb::eBasicTypeSignedChar;
9380b57cec5SDimitry Andric   case SimpleTypeKind::Character16:
9390b57cec5SDimitry Andric     return lldb::eBasicTypeChar16;
9400b57cec5SDimitry Andric   case SimpleTypeKind::Character32:
9410b57cec5SDimitry Andric     return lldb::eBasicTypeChar32;
94281ad6265SDimitry Andric   case SimpleTypeKind::Character8:
94381ad6265SDimitry Andric     return lldb::eBasicTypeChar8;
9440b57cec5SDimitry Andric   case SimpleTypeKind::Complex80:
9450b57cec5SDimitry Andric     return lldb::eBasicTypeLongDoubleComplex;
9460b57cec5SDimitry Andric   case SimpleTypeKind::Complex64:
9470b57cec5SDimitry Andric     return lldb::eBasicTypeDoubleComplex;
9480b57cec5SDimitry Andric   case SimpleTypeKind::Complex32:
9490b57cec5SDimitry Andric     return lldb::eBasicTypeFloatComplex;
9500b57cec5SDimitry Andric   case SimpleTypeKind::Float128:
9510b57cec5SDimitry Andric   case SimpleTypeKind::Float80:
9520b57cec5SDimitry Andric     return lldb::eBasicTypeLongDouble;
9530b57cec5SDimitry Andric   case SimpleTypeKind::Float64:
9540b57cec5SDimitry Andric     return lldb::eBasicTypeDouble;
9550b57cec5SDimitry Andric   case SimpleTypeKind::Float32:
9560b57cec5SDimitry Andric     return lldb::eBasicTypeFloat;
9570b57cec5SDimitry Andric   case SimpleTypeKind::Float16:
9580b57cec5SDimitry Andric     return lldb::eBasicTypeHalf;
9590b57cec5SDimitry Andric   case SimpleTypeKind::Int128:
9600b57cec5SDimitry Andric     return lldb::eBasicTypeInt128;
9610b57cec5SDimitry Andric   case SimpleTypeKind::Int64:
9620b57cec5SDimitry Andric   case SimpleTypeKind::Int64Quad:
9630b57cec5SDimitry Andric     return lldb::eBasicTypeLongLong;
9640b57cec5SDimitry Andric   case SimpleTypeKind::Int32:
9650b57cec5SDimitry Andric     return lldb::eBasicTypeInt;
9660b57cec5SDimitry Andric   case SimpleTypeKind::Int16:
9670b57cec5SDimitry Andric   case SimpleTypeKind::Int16Short:
9680b57cec5SDimitry Andric     return lldb::eBasicTypeShort;
9690b57cec5SDimitry Andric   case SimpleTypeKind::UInt128:
9700b57cec5SDimitry Andric     return lldb::eBasicTypeUnsignedInt128;
9710b57cec5SDimitry Andric   case SimpleTypeKind::UInt64:
9720b57cec5SDimitry Andric   case SimpleTypeKind::UInt64Quad:
9730b57cec5SDimitry Andric     return lldb::eBasicTypeUnsignedLongLong;
9740b57cec5SDimitry Andric   case SimpleTypeKind::HResult:
9750b57cec5SDimitry Andric   case SimpleTypeKind::UInt32:
9760b57cec5SDimitry Andric     return lldb::eBasicTypeUnsignedInt;
9770b57cec5SDimitry Andric   case SimpleTypeKind::UInt16:
9780b57cec5SDimitry Andric   case SimpleTypeKind::UInt16Short:
9790b57cec5SDimitry Andric     return lldb::eBasicTypeUnsignedShort;
9800b57cec5SDimitry Andric   case SimpleTypeKind::Int32Long:
9810b57cec5SDimitry Andric     return lldb::eBasicTypeLong;
9820b57cec5SDimitry Andric   case SimpleTypeKind::UInt32Long:
9830b57cec5SDimitry Andric     return lldb::eBasicTypeUnsignedLong;
9840b57cec5SDimitry Andric   case SimpleTypeKind::Void:
9850b57cec5SDimitry Andric     return lldb::eBasicTypeVoid;
9860b57cec5SDimitry Andric   case SimpleTypeKind::WideCharacter:
9870b57cec5SDimitry Andric     return lldb::eBasicTypeWChar;
9880b57cec5SDimitry Andric   default:
9890b57cec5SDimitry Andric     return lldb::eBasicTypeInvalid;
9900b57cec5SDimitry Andric   }
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
GetTypeSizeForSimpleKind(SimpleTypeKind kind)9930b57cec5SDimitry Andric size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
9940b57cec5SDimitry Andric   switch (kind) {
9950b57cec5SDimitry Andric   case SimpleTypeKind::Boolean128:
9960b57cec5SDimitry Andric   case SimpleTypeKind::Int128:
9970b57cec5SDimitry Andric   case SimpleTypeKind::UInt128:
9980b57cec5SDimitry Andric   case SimpleTypeKind::Float128:
9990b57cec5SDimitry Andric     return 16;
10000b57cec5SDimitry Andric   case SimpleTypeKind::Complex80:
10010b57cec5SDimitry Andric   case SimpleTypeKind::Float80:
10020b57cec5SDimitry Andric     return 10;
10030b57cec5SDimitry Andric   case SimpleTypeKind::Boolean64:
10040b57cec5SDimitry Andric   case SimpleTypeKind::Complex64:
10050b57cec5SDimitry Andric   case SimpleTypeKind::UInt64:
10060b57cec5SDimitry Andric   case SimpleTypeKind::UInt64Quad:
10070b57cec5SDimitry Andric   case SimpleTypeKind::Float64:
10080b57cec5SDimitry Andric   case SimpleTypeKind::Int64:
10090b57cec5SDimitry Andric   case SimpleTypeKind::Int64Quad:
10100b57cec5SDimitry Andric     return 8;
10110b57cec5SDimitry Andric   case SimpleTypeKind::Boolean32:
10120b57cec5SDimitry Andric   case SimpleTypeKind::Character32:
10130b57cec5SDimitry Andric   case SimpleTypeKind::Complex32:
10140b57cec5SDimitry Andric   case SimpleTypeKind::Float32:
10150b57cec5SDimitry Andric   case SimpleTypeKind::Int32:
10160b57cec5SDimitry Andric   case SimpleTypeKind::Int32Long:
10170b57cec5SDimitry Andric   case SimpleTypeKind::UInt32Long:
10180b57cec5SDimitry Andric   case SimpleTypeKind::HResult:
10190b57cec5SDimitry Andric   case SimpleTypeKind::UInt32:
10200b57cec5SDimitry Andric     return 4;
10210b57cec5SDimitry Andric   case SimpleTypeKind::Boolean16:
10220b57cec5SDimitry Andric   case SimpleTypeKind::Character16:
10230b57cec5SDimitry Andric   case SimpleTypeKind::Float16:
10240b57cec5SDimitry Andric   case SimpleTypeKind::Int16:
10250b57cec5SDimitry Andric   case SimpleTypeKind::Int16Short:
10260b57cec5SDimitry Andric   case SimpleTypeKind::UInt16:
10270b57cec5SDimitry Andric   case SimpleTypeKind::UInt16Short:
10280b57cec5SDimitry Andric   case SimpleTypeKind::WideCharacter:
10290b57cec5SDimitry Andric     return 2;
10300b57cec5SDimitry Andric   case SimpleTypeKind::Boolean8:
10310b57cec5SDimitry Andric   case SimpleTypeKind::Byte:
10320b57cec5SDimitry Andric   case SimpleTypeKind::UnsignedCharacter:
10330b57cec5SDimitry Andric   case SimpleTypeKind::NarrowCharacter:
10340b57cec5SDimitry Andric   case SimpleTypeKind::SignedCharacter:
10350b57cec5SDimitry Andric   case SimpleTypeKind::SByte:
103681ad6265SDimitry Andric   case SimpleTypeKind::Character8:
10370b57cec5SDimitry Andric     return 1;
10380b57cec5SDimitry Andric   case SimpleTypeKind::Void:
10390b57cec5SDimitry Andric   default:
10400b57cec5SDimitry Andric     return 0;
10410b57cec5SDimitry Andric   }
10420b57cec5SDimitry Andric }
10430b57cec5SDimitry Andric 
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)10440b57cec5SDimitry Andric PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
10450b57cec5SDimitry Andric                                                      TpiStream &tpi) {
10460b57cec5SDimitry Andric   if (id.index.isSimple())
10470b57cec5SDimitry Andric     return id;
10480b57cec5SDimitry Andric 
10490b57cec5SDimitry Andric   CVType cvt = tpi.getType(id.index);
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric   // Only tag records have a best and a worst record.
10520b57cec5SDimitry Andric   if (!IsTagRecord(cvt))
10530b57cec5SDimitry Andric     return id;
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric   // Tag records that are not forward decls are full decls, hence they are the
10560b57cec5SDimitry Andric   // best.
10570b57cec5SDimitry Andric   if (!IsForwardRefUdt(cvt))
10580b57cec5SDimitry Andric     return id;
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric   return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric 
GetSizeOfTypeInternal(CVType cvt)10630b57cec5SDimitry Andric template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
10640b57cec5SDimitry Andric   RecordType record;
10650b57cec5SDimitry Andric   llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
10660b57cec5SDimitry Andric   return record.getSize();
10670b57cec5SDimitry Andric }
10680b57cec5SDimitry Andric 
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)10690b57cec5SDimitry Andric size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
10700b57cec5SDimitry Andric                                          llvm::pdb::TpiStream &tpi) {
10710b57cec5SDimitry Andric   if (id.index.isSimple()) {
10720b57cec5SDimitry Andric     switch (id.index.getSimpleMode()) {
10730b57cec5SDimitry Andric     case SimpleTypeMode::Direct:
10740b57cec5SDimitry Andric       return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
10750b57cec5SDimitry Andric     case SimpleTypeMode::NearPointer32:
10760b57cec5SDimitry Andric     case SimpleTypeMode::FarPointer32:
10770b57cec5SDimitry Andric       return 4;
10780b57cec5SDimitry Andric     case SimpleTypeMode::NearPointer64:
10790b57cec5SDimitry Andric       return 8;
10800b57cec5SDimitry Andric     case SimpleTypeMode::NearPointer128:
10810b57cec5SDimitry Andric       return 16;
10820b57cec5SDimitry Andric     default:
10830b57cec5SDimitry Andric       break;
10840b57cec5SDimitry Andric     }
10850b57cec5SDimitry Andric     return 0;
10860b57cec5SDimitry Andric   }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   TypeIndex index = id.index;
10890b57cec5SDimitry Andric   if (IsForwardRefUdt(index, tpi))
10900b57cec5SDimitry Andric     index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   CVType cvt = tpi.getType(index);
10930b57cec5SDimitry Andric   switch (cvt.kind()) {
10940b57cec5SDimitry Andric   case LF_MODIFIER:
10950b57cec5SDimitry Andric     return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
10960b57cec5SDimitry Andric   case LF_ENUM: {
10970b57cec5SDimitry Andric     EnumRecord record;
10980b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
10990b57cec5SDimitry Andric     return GetSizeOfType({record.UnderlyingType}, tpi);
11000b57cec5SDimitry Andric   }
11010b57cec5SDimitry Andric   case LF_POINTER:
11020b57cec5SDimitry Andric     return GetSizeOfTypeInternal<PointerRecord>(cvt);
11030b57cec5SDimitry Andric   case LF_ARRAY:
11040b57cec5SDimitry Andric     return GetSizeOfTypeInternal<ArrayRecord>(cvt);
11050b57cec5SDimitry Andric   case LF_CLASS:
11060b57cec5SDimitry Andric   case LF_STRUCTURE:
11070b57cec5SDimitry Andric   case LF_INTERFACE:
11080b57cec5SDimitry Andric     return GetSizeOfTypeInternal<ClassRecord>(cvt);
11090b57cec5SDimitry Andric   case LF_UNION:
11100b57cec5SDimitry Andric     return GetSizeOfTypeInternal<UnionRecord>(cvt);
1111bdd1243dSDimitry Andric   case LF_BITFIELD: {
1112bdd1243dSDimitry Andric     BitFieldRecord record;
1113bdd1243dSDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));
1114bdd1243dSDimitry Andric     return GetSizeOfType({record.Type}, tpi);
1115bdd1243dSDimitry Andric   }
11160b57cec5SDimitry Andric   default:
11170b57cec5SDimitry Andric     break;
11180b57cec5SDimitry Andric   }
11190b57cec5SDimitry Andric   return 0;
11200b57cec5SDimitry Andric }
1121