Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZequan Wu <zequanwu@google.com>2022-09-23 20:57:25 +0300
committerZequan Wu <zequanwu@google.com>2022-09-27 21:01:32 +0300
commita3e60044d75823a3cd8e35de76b7bde2599fe740 (patch)
treec7b323fa4eb1bbe80be342f6002f72a90ff5c2d5
parent7da2b918878d1694fe52ab1da8ec988a36417da5 (diff)
[LLDB][NativePDB] Let native pdb use class layout in debug info.
Before, class layout in native pdb is not hooked up in [[https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp#L9375-L9380 | here]]. This changes hooked it up by refactoring SymbolFileNativePDB and PdbAstBuilder. PdbIndex (corresponds to a single pdb file) is removed from PdbAstBuilder, so it can only be accessed via SymbolFileNativePDB and we can construct PdbAstBuilder with just TypeSystemClang. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D134509
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp365
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h7
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp334
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h15
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp2
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp9
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h2
8 files changed, 432 insertions, 308 deletions
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 769449a4933b..57bdfa5b626a 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -31,6 +31,9 @@ class DWARFASTParser;
class PDBASTParser;
namespace lldb_private {
+namespace npdb {
+ class PdbAstBuilder;
+} // namespace npdb
/// A SmallBitVector that represents a set of source languages (\p
/// lldb::LanguageType). Each lldb::LanguageType is represented by
@@ -88,6 +91,7 @@ public:
virtual DWARFASTParser *GetDWARFParser() { return nullptr; }
virtual PDBASTParser *GetPDBParser() { return nullptr; }
+ virtual npdb::PdbAstBuilder *GetNativePDBParser() { return nullptr; }
virtual SymbolFile *GetSymbolFile() const { return m_sym_file; }
@@ -366,7 +370,7 @@ public:
LLVM_DUMP_METHOD virtual void
dump(lldb::opaque_compiler_type_t type) const = 0;
#endif
-
+
virtual void DumpValue(lldb::opaque_compiler_type_t type,
ExecutionContext *exe_ctx, Stream *s,
lldb::Format format, const DataExtractor &data,
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index ab467f20990c..2e17aa1260a8 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -24,6 +24,7 @@
#include "PdbUtil.h"
#include "UdtRecordCompleter.h"
+#include "SymbolFileNativePDB.h"
using namespace lldb_private;
using namespace lldb_private::npdb;
@@ -94,59 +95,6 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
};
} // namespace
-static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index,
- PdbCompilandSymId id) {
- CVSymbol sym = index.ReadSymbolRecord(id);
- if (symbolOpensScope(sym.kind())) {
- // If this exact symbol opens a scope, we can just directly access its
- // parent.
- id.offset = getScopeParentOffset(sym);
- // Global symbols have parent offset of 0. Return llvm::None to indicate
- // this.
- if (id.offset == 0)
- return llvm::None;
- return id;
- }
-
- // Otherwise we need to start at the beginning and iterate forward until we
- // reach (or pass) this particular symbol
- CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(id.modi);
- const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
-
- auto begin = syms.begin();
- auto end = syms.at(id.offset);
- std::vector<PdbCompilandSymId> scope_stack;
-
- while (begin != end) {
- if (begin.offset() > id.offset) {
- // We passed it. We couldn't even find this symbol record.
- lldbassert(false && "Invalid compiland symbol id!");
- return llvm::None;
- }
-
- // We haven't found the symbol yet. Check if we need to open or close the
- // scope stack.
- if (symbolOpensScope(begin->kind())) {
- // We can use the end offset of the scope to determine whether or not
- // we can just outright skip this entire scope.
- uint32_t scope_end = getScopeEndOffset(*begin);
- if (scope_end < id.offset) {
- begin = syms.at(scope_end);
- } else {
- // The symbol we're looking for is somewhere in this scope.
- scope_stack.emplace_back(id.modi, begin.offset());
- }
- } else if (symbolEndsScope(begin->kind())) {
- scope_stack.pop_back();
- }
- ++begin;
- }
- if (scope_stack.empty())
- return llvm::None;
- // We have a match! Return the top of the stack
- return scope_stack.back();
-}
-
static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
switch (cr.Kind) {
case TypeRecordKind::Class:
@@ -207,65 +155,11 @@ TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
}
}
-static llvm::Optional<CVTagRecord>
-GetNestedTagDefinition(const NestedTypeRecord &Record,
- const CVTagRecord &parent, TpiStream &tpi) {
- // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
- // is also used to indicate the primary definition of a nested class. That is
- // to say, if you have:
- // struct A {
- // struct B {};
- // using C = B;
- // };
- // Then in the debug info, this will appear as:
- // LF_STRUCTURE `A::B` [type index = N]
- // LF_STRUCTURE `A`
- // LF_NESTTYPE [name = `B`, index = N]
- // LF_NESTTYPE [name = `C`, index = N]
- // In order to accurately reconstruct the decl context hierarchy, we need to
- // know which ones are actual definitions and which ones are just aliases.
-
- // If it's a simple type, then this is something like `using foo = int`.
- if (Record.Type.isSimple())
- return llvm::None;
-
- CVType cvt = tpi.getType(Record.Type);
-
- if (!IsTagRecord(cvt))
- return llvm::None;
-
- // If it's an inner definition, then treat whatever name we have here as a
- // single component of a mangled name. So we can inject it into the parent's
- // mangled name to see if it matches.
- CVTagRecord child = CVTagRecord::create(cvt);
- std::string qname = std::string(parent.asTag().getUniqueName());
- if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
- return llvm::None;
-
- // qname[3] is the tag type identifier (struct, class, union, etc). Since the
- // inner tag type is not necessarily the same as the outer tag type, re-write
- // it to match the inner tag type.
- qname[3] = child.asTag().getUniqueName()[3];
- std::string piece;
- if (qname[3] == 'W')
- piece = "4";
- piece += Record.Name;
- piece.push_back('@');
- qname.insert(4, std::move(piece));
- if (qname != child.asTag().UniqueName)
- return llvm::None;
-
- return std::move(child);
-}
-
static bool IsAnonymousNamespaceName(llvm::StringRef name) {
return name == "`anonymous namespace'" || name == "`anonymous-namespace'";
}
-PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index, TypeSystemClang &clang)
- : m_index(index), m_clang(clang) {
- BuildParentMap();
-}
+PdbAstBuilder::PdbAstBuilder(TypeSystemClang &clang) : m_clang(clang) {}
lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() {
return ToCompilerDeclContext(*m_clang.GetTranslationUnitDecl());
@@ -273,6 +167,8 @@ lldb_private::CompilerDeclContext PdbAstBuilder::GetTranslationUnitDecl() {
std::pair<clang::DeclContext *, std::string>
PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
// FIXME: Move this to GetDeclContextContainingUID.
if (!record.hasUniqueName())
return CreateDeclInfoForUndecoratedName(record.Name);
@@ -297,8 +193,8 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
// If this type doesn't have a parent type in the debug info, then the best we
// can do is to say that it's either a series of namespaces (if the scope is
// non-empty), or the translation unit (if the scope is empty).
- auto parent_iter = m_parent_types.find(ti);
- if (parent_iter == m_parent_types.end()) {
+ llvm::Optional<TypeIndex> parent_index = pdb->GetParentType(ti);
+ if (!parent_index) {
if (scopes.empty())
return {context, uname};
@@ -322,7 +218,7 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
// recurse into our lazy type creation / AST reconstruction logic to get an
// LLDB TypeSP for the parent. This will cause the AST to automatically get
// the right DeclContext created for any parent.
- clang::QualType parent_qt = GetOrCreateType(parent_iter->second);
+ clang::QualType parent_qt = GetOrCreateType(*parent_index);
if (parent_qt.isNull())
return {nullptr, ""};
@@ -330,120 +226,6 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
return {context, uname};
}
-void PdbAstBuilder::BuildParentMap() {
- LazyRandomTypeCollection &types = m_index.tpi().typeCollection();
-
- llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
- llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
-
- struct RecordIndices {
- TypeIndex forward;
- TypeIndex full;
- };
-
- llvm::StringMap<RecordIndices> record_indices;
-
- for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
- CVType type = types.getType(*ti);
- if (!IsTagRecord(type))
- continue;
-
- CVTagRecord tag = CVTagRecord::create(type);
-
- RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
- if (tag.asTag().isForwardRef())
- indices.forward = *ti;
- else
- indices.full = *ti;
-
- if (indices.full != TypeIndex::None() &&
- indices.forward != TypeIndex::None()) {
- forward_to_full[indices.forward] = indices.full;
- full_to_forward[indices.full] = indices.forward;
- }
-
- // We're looking for LF_NESTTYPE records in the field list, so ignore
- // forward references (no field list), and anything without a nested class
- // (since there won't be any LF_NESTTYPE records).
- if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
- continue;
-
- struct ProcessTpiStream : public TypeVisitorCallbacks {
- ProcessTpiStream(PdbIndex &index, TypeIndex parent,
- const CVTagRecord &parent_cvt,
- llvm::DenseMap<TypeIndex, TypeIndex> &parents)
- : index(index), parents(parents), parent(parent),
- parent_cvt(parent_cvt) {}
-
- PdbIndex &index;
- llvm::DenseMap<TypeIndex, TypeIndex> &parents;
-
- unsigned unnamed_type_index = 1;
- TypeIndex parent;
- const CVTagRecord &parent_cvt;
-
- llvm::Error visitKnownMember(CVMemberRecord &CVR,
- NestedTypeRecord &Record) override {
- std::string unnamed_type_name;
- if (Record.Name.empty()) {
- unnamed_type_name =
- llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
- Record.Name = unnamed_type_name;
- ++unnamed_type_index;
- }
- llvm::Optional<CVTagRecord> tag =
- GetNestedTagDefinition(Record, parent_cvt, index.tpi());
- if (!tag)
- return llvm::ErrorSuccess();
-
- parents[Record.Type] = parent;
- return llvm::ErrorSuccess();
- }
- };
-
- CVType field_list_cvt = m_index.tpi().getType(tag.asTag().FieldList);
- ProcessTpiStream process(m_index, *ti, tag, m_parent_types);
- FieldListRecord field_list;
- if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
- field_list_cvt, field_list))
- llvm::consumeError(std::move(error));
- if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
- llvm::consumeError(std::move(error));
- }
-
- // Now that we know the forward -> full mapping of all type indices, we can
- // re-write all the indices. At the end of this process, we want a mapping
- // consisting of fwd -> full and full -> full for all child -> parent indices.
- // We can re-write the values in place, but for the keys, we must save them
- // off so that we don't modify the map in place while also iterating it.
- std::vector<TypeIndex> full_keys;
- std::vector<TypeIndex> fwd_keys;
- for (auto &entry : m_parent_types) {
- TypeIndex key = entry.first;
- TypeIndex value = entry.second;
-
- auto iter = forward_to_full.find(value);
- if (iter != forward_to_full.end())
- entry.second = iter->second;
-
- iter = forward_to_full.find(key);
- if (iter != forward_to_full.end())
- fwd_keys.push_back(key);
- else
- full_keys.push_back(key);
- }
- for (TypeIndex fwd : fwd_keys) {
- TypeIndex full = forward_to_full[fwd];
- m_parent_types[full] = m_parent_types[fwd];
- }
- for (TypeIndex full : full_keys) {
- TypeIndex fwd = full_to_forward[full];
- m_parent_types[fwd] = m_parent_types[full];
- }
-
- // Now that
-}
-
static bool isLocalVariableType(SymbolKind K) {
switch (K) {
case S_REGISTER:
@@ -457,7 +239,10 @@ static bool isLocalVariableType(SymbolKind K) {
}
clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
- CVSymbol cvs = m_index.ReadSymbolRecord(id);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol cvs = index.ReadSymbolRecord(id);
if (isLocalVariableType(cvs.kind())) {
clang::DeclContext *scope = GetParentDeclContext(id);
@@ -534,6 +319,9 @@ clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
std::pair<clang::DeclContext *, std::string>
PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
MSVCUndecoratedNameParser parser(name);
llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
@@ -547,7 +335,7 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
llvm::StringRef scope_name = specs.back().GetFullName();
// It might be a class name, try that first.
- std::vector<TypeIndex> types = m_index.tpi().findRecordsByName(scope_name);
+ std::vector<TypeIndex> types = index.tpi().findRecordsByName(scope_name);
while (!types.empty()) {
clang::QualType qt = GetOrCreateType(types.back());
if (qt.isNull())
@@ -569,24 +357,27 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
// We must do this *without* calling GetOrCreate on the current uid, as
// that would be an infinite recursion.
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex& index = pdb->GetIndex();
switch (uid.kind()) {
case PdbSymUidKind::CompilandSym: {
llvm::Optional<PdbCompilandSymId> scope =
- FindSymbolScope(m_index, uid.asCompilandSym());
+ pdb->FindSymbolScope(uid.asCompilandSym());
if (scope)
return GetOrCreateDeclContextForUid(*scope);
- CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym());
+ CVSymbol sym = index.ReadSymbolRecord(uid.asCompilandSym());
return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
}
case PdbSymUidKind::Type: {
// It could be a namespace, class, or global. We don't support nested
// functions yet. Anyway, we just need to consult the parent type map.
PdbTypeSymId type_id = uid.asTypeSym();
- auto iter = m_parent_types.find(type_id.index);
- if (iter == m_parent_types.end())
+ llvm::Optional<TypeIndex> parent_index = pdb->GetParentType(type_id.index);
+ if (!parent_index)
return FromCompilerDeclContext(GetTranslationUnitDecl());
- return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second));
+ return GetOrCreateDeclContextForUid(PdbTypeSymId(*parent_index));
}
case PdbSymUidKind::FieldListMember:
// In this case the parent DeclContext is the one for the class that this
@@ -599,7 +390,7 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
// that up in the TPI stream. If it's found, it's a type, othewrise it's
// a series of namespaces.
// FIXME: do this.
- CVSymbol global = m_index.ReadSymbolRecord(uid.asGlobalSym());
+ CVSymbol global = index.ReadSymbolRecord(uid.asGlobalSym());
switch (global.kind()) {
case SymbolKind::S_GDATA32:
case SymbolKind::S_LDATA32:
@@ -651,19 +442,21 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
return true;
PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym();
-
- lldbassert(IsTagRecord(type_id, m_index.tpi()));
+ PdbIndex &index = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile())
+ ->GetIndex();
+ lldbassert(IsTagRecord(type_id, index.tpi()));
clang::QualType tag_qt = m_clang.getASTContext().getTypeDeclType(&tag);
TypeSystemClang::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);
TypeIndex tag_ti = type_id.index;
- CVType cvt = m_index.tpi().getType(tag_ti);
+ CVType cvt = index.tpi().getType(tag_ti);
if (cvt.kind() == LF_MODIFIER)
tag_ti = LookThroughModifierRecord(cvt);
- PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, m_index.tpi());
- cvt = m_index.tpi().getType(best_ti.index);
+ PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, index.tpi());
+ cvt = index.tpi().getType(best_ti.index);
lldbassert(IsTagRecord(cvt));
if (IsForwardRefUdt(cvt)) {
@@ -673,7 +466,7 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
}
TypeIndex field_list_ti = GetFieldListIndex(cvt);
- CVType field_list_cvt = m_index.tpi().getType(field_list_ti);
+ CVType field_list_cvt = index.tpi().getType(field_list_ti);
if (field_list_cvt.kind() != LF_FIELDLIST)
return false;
FieldListRecord field_list;
@@ -684,7 +477,7 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
// Visit all members of this class, then perform any finalization necessary
// to complete the class.
CompilerType ct = ToCompilerType(tag_qt);
- UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index,
+ UdtRecordCompleter completer(best_ti, ct, tag, *this, index,
m_cxx_record_map);
llvm::Error error =
llvm::codeview::visitMemberRecordStream(field_list.Data, completer);
@@ -900,7 +693,10 @@ PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
if (!scope)
return nullptr;
- CVSymbol sym = m_index.ReadSymbolRecord(var_id);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol sym = index.ReadSymbolRecord(var_id);
return CreateVariableDecl(PdbSymUid(var_id), sym, *scope);
}
@@ -908,7 +704,10 @@ clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {
if (clang::Decl *decl = TryGetDecl(var_id))
return llvm::dyn_cast<clang::VarDecl>(decl);
- CVSymbol sym = m_index.ReadSymbolRecord(var_id);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol sym = index.ReadSymbolRecord(var_id);
auto context = FromCompilerDeclContext(GetTranslationUnitDecl());
return CreateVariableDecl(PdbSymUid(var_id), sym, *context);
}
@@ -918,7 +717,10 @@ PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
if (clang::Decl *decl = TryGetDecl(id))
return llvm::dyn_cast<clang::TypedefNameDecl>(decl);
- CVSymbol sym = m_index.ReadSymbolRecord(id);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol sym = index.ReadSymbolRecord(id);
lldbassert(sym.kind() == S_UDT);
UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
@@ -950,7 +752,10 @@ clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) {
if (type.index.isSimple())
return CreateSimpleType(type.index);
- CVType cvt = m_index.tpi().getType(type.index);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVType cvt = index.tpi().getType(type.index);
if (cvt.kind() == LF_MODIFIER) {
ModifierRecord modifier;
@@ -1006,7 +811,10 @@ clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
if (iter != m_uid_to_type.end())
return iter->second;
- PdbTypeSymId best_type = GetBestPossibleDecl(type, m_index.tpi());
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ PdbTypeSymId best_type = GetBestPossibleDecl(type, index.tpi());
clang::QualType qt;
if (best_type.index != type.index) {
@@ -1026,7 +834,7 @@ clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
return {};
m_uid_to_type[toOpaqueUid(type)] = qt;
- if (IsTagRecord(type, m_index.tpi())) {
+ if (IsTagRecord(type, index.tpi())) {
clang::TagDecl *tag = qt->getAsTagDecl();
lldbassert(m_decl_to_status.count(tag) == 0);
@@ -1045,6 +853,9 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
bool is_inline, clang::DeclContext *parent) {
clang::FunctionDecl *function_decl = nullptr;
if (parent->isRecord()) {
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
clang::QualType parent_qt = llvm::cast<clang::TypeDecl>(parent)
->getTypeForDecl()
->getCanonicalTypeInternal();
@@ -1058,29 +869,29 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
}
}
- CVType cvt = m_index.tpi().getType(func_ti);
+ CVType cvt = index.tpi().getType(func_ti);
MemberFunctionRecord func_record(static_cast<TypeRecordKind>(cvt.kind()));
llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(
cvt, func_record));
TypeIndex class_index = func_record.getClassType();
- CVType parent_cvt = m_index.tpi().getType(class_index);
+ CVType parent_cvt = index.tpi().getType(class_index);
TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag();
// If it's a forward reference, try to get the real TypeIndex.
if (tag_record.isForwardRef()) {
llvm::Expected<TypeIndex> eti =
- m_index.tpi().findFullDeclForForwardRef(class_index);
+ index.tpi().findFullDeclForForwardRef(class_index);
if (eti) {
- tag_record = CVTagRecord::create(m_index.tpi().getType(*eti)).asTag();
+ tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag();
}
}
if (!tag_record.FieldList.isSimple()) {
- CVType field_list_cvt = m_index.tpi().getType(tag_record.FieldList);
+ CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
FieldListRecord field_list;
if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
field_list_cvt, field_list))
llvm::consumeError(std::move(error));
- CreateMethodDecl process(m_index, m_clang, func_ti, function_decl,
+ CreateMethodDecl process(index, m_clang, func_ti, function_decl,
parent_opaque_ty, func_name, func_ct);
if (llvm::Error err = visitMemberRecordStream(field_list.Data, process))
llvm::consumeError(std::move(err));
@@ -1107,8 +918,11 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
clang::FunctionDecl *
PdbAstBuilder::GetOrCreateInlinedFunctionDecl(PdbCompilandSymId inlinesite_id) {
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
CompilandIndexItem *cii =
- m_index.compilands().GetCompiland(inlinesite_id.modi);
+ index.compilands().GetCompiland(inlinesite_id.modi);
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(inlinesite_id.offset);
InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));
@@ -1145,7 +959,10 @@ clang::FunctionDecl *
PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid,
PdbCompilandSymId func_sid) {
lldbassert(func_tid.is_ipi);
- CVType func_cvt = m_index.ipi().getType(func_tid.index);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVType func_cvt = index.ipi().getType(func_tid.index);
llvm::StringRef func_name;
TypeIndex func_ti;
clang::DeclContext *parent = nullptr;
@@ -1167,7 +984,7 @@ PdbAstBuilder::CreateFunctionDeclFromId(PdbTypeSymId func_tid,
func_ti = fir.getFunctionType();
parent = FromCompilerDeclContext(GetTranslationUnitDecl());
if (!fir.ParentScope.isNoneType()) {
- CVType parent_cvt = m_index.ipi().getType(fir.ParentScope);
+ CVType parent_cvt = index.ipi().getType(fir.ParentScope);
if (parent_cvt.kind() == LF_STRING_ID) {
StringIdRecord sir;
cantFail(
@@ -1205,7 +1022,10 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
context_name = tag->getQualifiedNameAsString();
}
- CVSymbol cvs = m_index.ReadSymbolRecord(func_id);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol cvs = index.ReadSymbolRecord(func_id);
ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));
llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc));
@@ -1245,7 +1065,10 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
clang::FunctionDecl &function_decl,
uint32_t param_count) {
- CompilandIndexItem *cii = m_index.compilands().GetCompiland(func_id.modi);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CompilandIndexItem *cii = index.compilands().GetCompiland(func_id.modi);
CVSymbolArray scope =
cii->m_debug_stream.getSymbolArrayForScope(func_id.offset);
@@ -1340,7 +1163,10 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) {
clang::QualType element_type = GetOrCreateType(ar.ElementType);
- uint64_t element_size = GetSizeOfType({ar.ElementType}, m_index.tpi());
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ uint64_t element_size = GetSizeOfType({ar.ElementType}, index.tpi());
if (element_type.isNull() || element_size == 0)
return {};
uint64_t element_count = ar.Size / element_size;
@@ -1353,7 +1179,10 @@ clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) {
clang::QualType PdbAstBuilder::CreateFunctionType(
TypeIndex args_type_idx, TypeIndex return_type_idx,
llvm::codeview::CallingConvention calling_convention) {
- TpiStream &stream = m_index.tpi();
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ TpiStream &stream = index.tpi();
CVType args_cvt = stream.getType(args_type_idx);
ArgListRecord args;
llvm::cantFail(
@@ -1405,8 +1234,11 @@ static bool isBlockDecl(clang::DeclContext &context) {
void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf(
llvm::Optional<llvm::StringRef> parent) {
- TypeIndex ti{m_index.tpi().TypeIndexBegin()};
- for (const CVType &cvt : m_index.tpi().typeArray()) {
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ TypeIndex ti{index.tpi().TypeIndexBegin()};
+ for (const CVType &cvt : index.tpi().typeArray()) {
PdbTypeSymId tid{ti};
++ti;
@@ -1439,9 +1271,9 @@ void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf(
}
}
- uint32_t module_count = m_index.dbi().modules().getModuleCount();
+ uint32_t module_count = index.dbi().modules().getModuleCount();
for (uint16_t modi = 0; modi < module_count; ++modi) {
- CompilandIndexItem &cii = m_index.compilands().GetOrCreateCompiland(modi);
+ CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(modi);
const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray();
auto iter = symbols.begin();
while (iter != symbols.end()) {
@@ -1495,11 +1327,14 @@ static CVSymbolArray skipFunctionParameters(clang::Decl &decl,
}
void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) {
- CVSymbol sym = m_index.ReadSymbolRecord(block_id);
+ SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>(
+ m_clang.GetSymbolFile()->GetBackingSymbolFile());
+ PdbIndex &index = pdb->GetIndex();
+ CVSymbol sym = index.ReadSymbolRecord(block_id);
lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 ||
sym.kind() == S_BLOCK32 || sym.kind() == S_INLINESITE);
CompilandIndexItem &cii =
- m_index.compilands().GetOrCreateCompiland(block_id.modi);
+ index.compilands().GetOrCreateCompiland(block_id.modi);
CVSymbolArray symbols =
cii.m_debug_stream.getSymbolArrayForScope(block_id.offset);
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
index e4d9c6e6e0bb..b94176e815e0 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -51,7 +51,7 @@ struct DeclStatus {
class PdbAstBuilder {
public:
// Constructors and Destructors
- PdbAstBuilder(ObjectFile &obj, PdbIndex &index, TypeSystemClang &clang);
+ PdbAstBuilder(TypeSystemClang &clang);
lldb_private::CompilerDeclContext GetTranslationUnitDecl();
@@ -83,7 +83,7 @@ public:
clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context);
TypeSystemClang &clang() { return m_clang; }
- ClangASTImporter &importer() { return m_importer; }
+ ClangASTImporter &GetClangASTImporter() { return m_importer; }
void Dump(Stream &stream);
@@ -126,19 +126,16 @@ private:
void ParseDeclsForSimpleContext(clang::DeclContext &context);
void ParseBlockChildren(PdbCompilandSymId block_id);
- void BuildParentMap();
std::pair<clang::DeclContext *, std::string>
CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti);
std::pair<clang::DeclContext *, std::string>
CreateDeclInfoForUndecoratedName(llvm::StringRef uname);
clang::QualType CreateSimpleType(TypeIndex ti);
- PdbIndex &m_index;
TypeSystemClang &m_clang;
ClangASTImporter m_importer;
- llvm::DenseMap<TypeIndex, TypeIndex> m_parent_types;
llvm::DenseMap<clang::Decl *, DeclStatus> m_decl_to_status;
llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl;
llvm::DenseMap<lldb::user_id_t, clang::QualType> m_uid_to_type;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 304b64904352..a34ce045e675 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -8,12 +8,6 @@
#include "SymbolFileNativePDB.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Type.h"
-
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
@@ -59,7 +53,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "DWARFLocationExpression.h"
-#include "PdbAstBuilder.h"
#include "PdbSymUid.h"
#include "PdbUtil.h"
#include "UdtRecordCompleter.h"
@@ -233,6 +226,57 @@ static bool IsClassRecord(TypeLeafKind kind) {
}
}
+static llvm::Optional<CVTagRecord>
+GetNestedTagDefinition(const NestedTypeRecord &Record,
+ const CVTagRecord &parent, TpiStream &tpi) {
+ // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
+ // is also used to indicate the primary definition of a nested class. That is
+ // to say, if you have:
+ // struct A {
+ // struct B {};
+ // using C = B;
+ // };
+ // Then in the debug info, this will appear as:
+ // LF_STRUCTURE `A::B` [type index = N]
+ // LF_STRUCTURE `A`
+ // LF_NESTTYPE [name = `B`, index = N]
+ // LF_NESTTYPE [name = `C`, index = N]
+ // In order to accurately reconstruct the decl context hierarchy, we need to
+ // know which ones are actual definitions and which ones are just aliases.
+
+ // If it's a simple type, then this is something like `using foo = int`.
+ if (Record.Type.isSimple())
+ return llvm::None;
+
+ CVType cvt = tpi.getType(Record.Type);
+
+ if (!IsTagRecord(cvt))
+ return llvm::None;
+
+ // If it's an inner definition, then treat whatever name we have here as a
+ // single component of a mangled name. So we can inject it into the parent's
+ // mangled name to see if it matches.
+ CVTagRecord child = CVTagRecord::create(cvt);
+ std::string qname = std::string(parent.asTag().getUniqueName());
+ if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
+ return llvm::None;
+
+ // qname[3] is the tag type identifier (struct, class, union, etc). Since the
+ // inner tag type is not necessarily the same as the outer tag type, re-write
+ // it to match the inner tag type.
+ qname[3] = child.asTag().getUniqueName()[3];
+ std::string piece;
+ if (qname[3] == 'W')
+ piece = "4";
+ piece += Record.Name;
+ piece.push_back('@');
+ qname.insert(4, std::move(piece));
+ if (qname != child.asTag().UniqueName)
+ return llvm::None;
+
+ return std::move(child);
+}
+
void SymbolFileNativePDB::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance,
@@ -311,9 +355,7 @@ void SymbolFileNativePDB::InitializeObject() {
"Failed to initialize");
} else {
ts_or_err->SetSymbolFile(this);
- auto *clang = llvm::cast_or_null<TypeSystemClang>(&ts_or_err.get());
- lldbassert(clang);
- m_ast = std::make_unique<PdbAstBuilder>(*m_objfile_sp, *m_index, *clang);
+ BuildParentMap();
}
}
@@ -338,6 +380,10 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return *child_block;
+ PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
switch (sym.kind()) {
case S_GPROC32:
@@ -381,7 +427,7 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
block_base + block.CodeSize, func_base);
}
parent_block.AddChild(child_block);
- m_ast->GetOrCreateBlockDecl(block_id);
+ ast_builder->GetOrCreateBlockDecl(block_id);
m_blocks.insert({opaque_block_uid, child_block});
break;
}
@@ -392,7 +438,7 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
Block &parent_block = GetOrCreateBlock(inline_site->parent_id);
parent_block.AddChild(child_block);
- m_ast->GetOrCreateInlinedFunctionDecl(block_id);
+ ast_builder->GetOrCreateInlinedFunctionDecl(block_id);
// Copy ranges from InlineSite to Block.
for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
auto *entry = inline_site->ranges.GetEntryAtIndex(i);
@@ -453,7 +499,10 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
comp_unit.AddFunction(func_sp);
- m_ast->GetOrCreateFunctionDecl(func_id);
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return func_sp;
+ ts_or_err->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);
return func_sp;
}
@@ -746,12 +795,15 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
}
PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
-
- clang::QualType qt = m_ast->GetOrCreateType(best_decl_id);
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
+ clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);
if (qt.isNull())
return nullptr;
- TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt));
+ TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));
if (!result)
return nullptr;
@@ -840,8 +892,10 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
SymbolFileTypeSP type_sp =
std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
Variable::RangeList ranges;
-
- m_ast->GetOrCreateVariableDecl(var_id);
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ ts_or_err->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);
ModuleSP module_sp = GetObjectFile()->GetModule();
DWARFExpressionList location(
@@ -941,10 +995,14 @@ Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
void SymbolFileNativePDB::ParseDeclsForContext(
lldb_private::CompilerDeclContext decl_ctx) {
- clang::DeclContext *context = m_ast->FromCompilerDeclContext(decl_ctx);
+ TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();
+ if (!ts_or_err)
+ return;
+ PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
+ clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);
if (!context)
return;
- m_ast->ParseDeclsForContext(*context);
+ ast_builder->ParseDeclsForContext(*context);
}
lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
@@ -1563,7 +1621,16 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
return count;
}
-void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); }
+void SymbolFileNativePDB::DumpClangAST(Stream &s) {
+ auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
+ if (!ts_or_err)
+ return;
+ TypeSystemClang *clang =
+ llvm::dyn_cast_or_null<TypeSystemClang>(&ts_or_err.get());
+ if (!clang)
+ return;
+ clang->GetNativePDBParser()->Dump(s);
+}
void SymbolFileNativePDB::FindGlobalVariables(
ConstString name, const CompilerDeclContext &parent_decl_ctx,
@@ -1767,8 +1834,12 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
&block, scope_ranges, &decl, var_info.location, external, artificial,
location_is_constant_data, static_member);
- if (!is_param)
- m_ast->GetOrCreateVariableDecl(scope_id, var_id);
+ if (!is_param) {
+ auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ ts_or_err->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);
+ }
m_local_variables[toOpaqueUid(var_id)] = var_sp;
return var_sp;
}
@@ -1790,7 +1861,10 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
TypeSP target_type = GetOrCreateType(udt.Type);
- (void)m_ast->GetOrCreateTypedefDecl(id);
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return nullptr;
+ ts_or_err->GetNativePDBParser()->GetOrCreateTypedefDecl(id);
Declaration decl;
return std::make_shared<lldb_private::Type>(
@@ -1924,28 +1998,38 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
}
CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
- if (auto decl = m_ast->GetOrCreateDeclForUid(uid))
- return *decl;
- else
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
return CompilerDecl();
+ if (auto decl = ts_or_err->GetNativePDBParser()->GetOrCreateDeclForUid(uid))
+ return *decl;
+ return CompilerDecl();
}
CompilerDeclContext
SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return {};
+ PdbAstBuilder *ast_builder = ts_or_err->GetNativePDBParser();
clang::DeclContext *context =
- m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid));
+ ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
if (!context)
return {};
- return m_ast->ToCompilerDeclContext(*context);
+ return ast_builder->ToCompilerDeclContext(*context);
}
CompilerDeclContext
SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
- clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid));
+ auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (auto err = ts_or_err.takeError())
+ return CompilerDeclContext();
+ PdbAstBuilder *ast_builder = ts_or_err->GetNativePDBParser();
+ clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));
if (!context)
return CompilerDeclContext();
- return m_ast->ToCompilerDeclContext(*context);
+ return ast_builder->ToCompilerDeclContext(*context);
}
Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -1977,12 +2061,23 @@ SymbolFileNativePDB::GetDynamicArrayInfoForUID(
return llvm::None;
}
-
bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+
+ TypeSystemClang *clang_type_system =
+ llvm::dyn_cast_or_null<TypeSystemClang>(compiler_type.GetTypeSystem());
+ if (!clang_type_system)
+ return false;
+
+ PdbAstBuilder *ast_builder =
+ static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());
+ if (ast_builder &&
+ ast_builder->GetClangASTImporter().CanImport(compiler_type))
+ return ast_builder->GetClangASTImporter().CompleteType(compiler_type);
clang::QualType qt =
clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
- return m_ast->CompleteType(qt);
+ return ast_builder->CompleteType(qt);
}
void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
@@ -2009,3 +2104,176 @@ uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
// PDB files are a separate file that contains all debug info.
return m_index->pdb().getFileSize();
}
+
+void SymbolFileNativePDB::BuildParentMap() {
+ LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
+
+ llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
+ llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
+
+ struct RecordIndices {
+ TypeIndex forward;
+ TypeIndex full;
+ };
+
+ llvm::StringMap<RecordIndices> record_indices;
+
+ for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+ CVType type = types.getType(*ti);
+ if (!IsTagRecord(type))
+ continue;
+
+ CVTagRecord tag = CVTagRecord::create(type);
+
+ RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
+ if (tag.asTag().isForwardRef())
+ indices.forward = *ti;
+ else
+ indices.full = *ti;
+
+ if (indices.full != TypeIndex::None() &&
+ indices.forward != TypeIndex::None()) {
+ forward_to_full[indices.forward] = indices.full;
+ full_to_forward[indices.full] = indices.forward;
+ }
+
+ // We're looking for LF_NESTTYPE records in the field list, so ignore
+ // forward references (no field list), and anything without a nested class
+ // (since there won't be any LF_NESTTYPE records).
+ if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
+ continue;
+
+ struct ProcessTpiStream : public TypeVisitorCallbacks {
+ ProcessTpiStream(PdbIndex &index, TypeIndex parent,
+ const CVTagRecord &parent_cvt,
+ llvm::DenseMap<TypeIndex, TypeIndex> &parents)
+ : index(index), parents(parents), parent(parent),
+ parent_cvt(parent_cvt) {}
+
+ PdbIndex &index;
+ llvm::DenseMap<TypeIndex, TypeIndex> &parents;
+
+ unsigned unnamed_type_index = 1;
+ TypeIndex parent;
+ const CVTagRecord &parent_cvt;
+
+ llvm::Error visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Record) override {
+ std::string unnamed_type_name;
+ if (Record.Name.empty()) {
+ unnamed_type_name =
+ llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
+ Record.Name = unnamed_type_name;
+ ++unnamed_type_index;
+ }
+ llvm::Optional<CVTagRecord> tag =
+ GetNestedTagDefinition(Record, parent_cvt, index.tpi());
+ if (!tag)
+ return llvm::ErrorSuccess();
+
+ parents[Record.Type] = parent;
+ return llvm::ErrorSuccess();
+ }
+ };
+
+ CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
+ ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
+ FieldListRecord field_list;
+ if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
+ field_list_cvt, field_list))
+ llvm::consumeError(std::move(error));
+ if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
+ llvm::consumeError(std::move(error));
+ }
+
+ // Now that we know the forward -> full mapping of all type indices, we can
+ // re-write all the indices. At the end of this process, we want a mapping
+ // consisting of fwd -> full and full -> full for all child -> parent indices.
+ // We can re-write the values in place, but for the keys, we must save them
+ // off so that we don't modify the map in place while also iterating it.
+ std::vector<TypeIndex> full_keys;
+ std::vector<TypeIndex> fwd_keys;
+ for (auto &entry : m_parent_types) {
+ TypeIndex key = entry.first;
+ TypeIndex value = entry.second;
+
+ auto iter = forward_to_full.find(value);
+ if (iter != forward_to_full.end())
+ entry.second = iter->second;
+
+ iter = forward_to_full.find(key);
+ if (iter != forward_to_full.end())
+ fwd_keys.push_back(key);
+ else
+ full_keys.push_back(key);
+ }
+ for (TypeIndex fwd : fwd_keys) {
+ TypeIndex full = forward_to_full[fwd];
+ m_parent_types[full] = m_parent_types[fwd];
+ }
+ for (TypeIndex full : full_keys) {
+ TypeIndex fwd = full_to_forward[full];
+ m_parent_types[fwd] = m_parent_types[full];
+ }
+}
+
+llvm::Optional<PdbCompilandSymId>
+SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
+ CVSymbol sym = m_index->ReadSymbolRecord(id);
+ if (symbolOpensScope(sym.kind())) {
+ // If this exact symbol opens a scope, we can just directly access its
+ // parent.
+ id.offset = getScopeParentOffset(sym);
+ // Global symbols have parent offset of 0. Return llvm::None to indicate
+ // this.
+ if (id.offset == 0)
+ return llvm::None;
+ return id;
+ }
+
+ // Otherwise we need to start at the beginning and iterate forward until we
+ // reach (or pass) this particular symbol
+ CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
+ const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+
+ auto begin = syms.begin();
+ auto end = syms.at(id.offset);
+ std::vector<PdbCompilandSymId> scope_stack;
+
+ while (begin != end) {
+ if (begin.offset() > id.offset) {
+ // We passed it. We couldn't even find this symbol record.
+ lldbassert(false && "Invalid compiland symbol id!");
+ return llvm::None;
+ }
+
+ // We haven't found the symbol yet. Check if we need to open or close the
+ // scope stack.
+ if (symbolOpensScope(begin->kind())) {
+ // We can use the end offset of the scope to determine whether or not
+ // we can just outright skip this entire scope.
+ uint32_t scope_end = getScopeEndOffset(*begin);
+ if (scope_end < id.offset) {
+ begin = syms.at(scope_end);
+ } else {
+ // The symbol we're looking for is somewhere in this scope.
+ scope_stack.emplace_back(id.modi, begin.offset());
+ }
+ } else if (symbolEndsScope(begin->kind())) {
+ scope_stack.pop_back();
+ }
+ ++begin;
+ }
+ if (scope_stack.empty())
+ return llvm::None;
+ // We have a match! Return the top of the stack
+ return scope_stack.back();
+}
+
+llvm::Optional<llvm::codeview::TypeIndex>
+SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
+ auto parent_iter = m_parent_types.find(ti);
+ if (parent_iter == m_parent_types.end())
+ return llvm::None;
+ return parent_iter->second;
+}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 4bb37d9e7675..51ed1212d53b 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -19,6 +19,7 @@
#include "CompileUnitIndex.h"
#include "PdbIndex.h"
+#include "PdbAstBuilder.h"
namespace clang {
class TagDecl;
@@ -37,7 +38,6 @@ struct UnionRecord;
namespace lldb_private {
namespace npdb {
-class PdbAstBuilder;
class SymbolFileNativePDB : public SymbolFileCommon {
friend class UdtRecordCompleter;
@@ -137,6 +137,8 @@ public:
void FindFunctions(const RegularExpression &regex, bool include_inlines,
SymbolContextList &sc_list) override;
+ llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id);
+
void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
uint32_t max_matches,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
@@ -158,8 +160,13 @@ public:
llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); }
const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); }
+ PdbIndex &GetIndex() { return *m_index; };
+
void DumpClangAST(Stream &s) override;
+ llvm::Optional<llvm::codeview::TypeIndex>
+ GetParentType(llvm::codeview::TypeIndex ti);
+
private:
struct LineTableEntryComparator {
bool operator()(const lldb_private::LineTable::Entry &lhs,
@@ -180,6 +187,8 @@ private:
InlineSite(PdbCompilandSymId parent_id) : parent_id(parent_id){};
};
+ void BuildParentMap();
+
uint32_t CalculateNumCompileUnits() override;
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
@@ -262,8 +271,6 @@ private:
std::unique_ptr<llvm::pdb::PDBFile> m_file_up;
std::unique_ptr<PdbIndex> m_index;
- std::unique_ptr<PdbAstBuilder> m_ast;
-
llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars;
llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables;
llvm::DenseMap<lldb::user_id_t, lldb::BlockSP> m_blocks;
@@ -271,6 +278,8 @@ private:
llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands;
llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;
llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites;
+ llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex>
+ m_parent_types;
};
} // namespace npdb
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index c0308196c760..16e9990ff3f0 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -312,6 +312,6 @@ void UdtRecordCompleter::complete() {
TypeSystemClang::CompleteTagDeclarationDefinition(m_derived_ct);
if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
- m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
+ m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, m_layout);
}
}
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 7e0a19c6b8bf..4adf653b6c50 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -73,6 +73,7 @@
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
+#include "Plugins/SymbolFile/NativePDB/PdbAstBuilder.h"
#include <cstdio>
@@ -9364,6 +9365,12 @@ PDBASTParser *TypeSystemClang::GetPDBParser() {
return m_pdb_ast_parser_up.get();
}
+npdb::PdbAstBuilder *TypeSystemClang::GetNativePDBParser() {
+ if (!m_native_pdb_ast_parser_up)
+ m_native_pdb_ast_parser_up = std::make_unique<npdb::PdbAstBuilder>(*this);
+ return m_native_pdb_ast_parser_up.get();
+}
+
bool TypeSystemClang::LayoutRecordType(
const clang::RecordDecl *record_decl, uint64_t &bit_size,
uint64_t &alignment,
@@ -9377,6 +9384,8 @@ bool TypeSystemClang::LayoutRecordType(
importer = &m_dwarf_ast_parser_up->GetClangASTImporter();
if (!importer && m_pdb_ast_parser_up)
importer = &m_pdb_ast_parser_up->GetClangASTImporter();
+ if (!importer && m_native_pdb_ast_parser_up)
+ importer = &m_native_pdb_ast_parser_up->GetClangASTImporter();
if (!importer)
return false;
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index ff8e12e821d1..7c045fdf088c 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -443,6 +443,7 @@ public:
// TypeSystem methods
DWARFASTParser *GetDWARFParser() override;
PDBASTParser *GetPDBParser() override;
+ npdb::PdbAstBuilder *GetNativePDBParser() override;
// TypeSystemClang callbacks for external source lookups.
void CompleteTagDecl(clang::TagDecl *);
@@ -1071,6 +1072,7 @@ private:
std::unique_ptr<clang::ModuleMap> m_module_map_up;
std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_up;
std::unique_ptr<PDBASTParser> m_pdb_ast_parser_up;
+ std::unique_ptr<npdb::PdbAstBuilder> m_native_pdb_ast_parser_up;
std::unique_ptr<clang::MangleContext> m_mangle_ctx_up;
uint32_t m_pointer_byte_size = 0;
bool m_ast_owned = false;