summaryrefslogtreecommitdiff
path: root/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-12-17 19:43:33 +0000
committerZachary Turner <zturner@google.com>2018-12-17 19:43:33 +0000
commitd5a300477a85fcdbdf194e96b951197a038a92bf (patch)
treeb436e8bfc8835983eb031cbbd516714a5b8cccb2 /source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
parent6f57bf9c666a81c2714d689b33e56f2b99a906e4 (diff)
[NativePDB] Decouple AST reconstruction from lldb Symbol creation.
Previously the code that parsed debug info to create lldb's Symbol objects such as Variable, Type, Function, etc was tightly coupled to the AST reconstruction code. This made it difficult / impossible to implement functions such as ParseDeclsForContext() that were only supposed to be operating on clang AST's. By splitting these apart, the logic becomes much cleaner and we have a clear separation of responsibilities. git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@349383 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp')
-rw-r--r--source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp820
1 files changed, 93 insertions, 727 deletions
diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index c7882e981..fa1688998 100644
--- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -56,6 +56,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "DWARFLocationExpression.h"
+#include "PdbAstBuilder.h"
#include "PdbSymUid.h"
#include "PdbUtil.h"
#include "UdtRecordCompleter.h"
@@ -66,15 +67,6 @@ using namespace npdb;
using namespace llvm::codeview;
using namespace llvm::pdb;
-namespace {
-struct VariableInfo {
- llvm::StringRef name;
- TypeIndex type;
- llvm::Optional<DWARFExpression> location;
- llvm::Optional<Variable::RangeList> ranges;
-};
-} // namespace
-
static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
switch (lang) {
case PDB_Lang::Cpp:
@@ -171,30 +163,6 @@ static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
return false;
}
-static clang::MSInheritanceAttr::Spelling
-GetMSInheritance(LazyRandomTypeCollection &tpi, const ClassRecord &record) {
- if (record.DerivationList == TypeIndex::None())
- return clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance;
-
- CVType bases = tpi.getType(record.DerivationList);
- ArgListRecord base_list;
- cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(bases, base_list));
- if (base_list.ArgIndices.empty())
- return clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance;
-
- int base_count = 0;
- for (TypeIndex ti : base_list.ArgIndices) {
- CVType base = tpi.getType(ti);
- if (base.kind() == LF_VBCLASS || base.kind() == LF_IVBCLASS)
- return clang::MSInheritanceAttr::Spelling::Keyword_virtual_inheritance;
- ++base_count;
- }
-
- if (base_count > 1)
- return clang::MSInheritanceAttr::Keyword_multiple_inheritance;
- return clang::MSInheritanceAttr::Keyword_single_inheritance;
-}
-
static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
switch (kind) {
case SimpleTypeKind::Boolean128:
@@ -273,144 +241,6 @@ static bool IsClassRecord(TypeLeafKind kind) {
}
}
-static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) {
- if (args.empty())
- return false;
- return args.back() == TypeIndex::None();
-}
-
-static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
- switch (cr.Kind) {
- case TypeRecordKind::Class:
- return clang::TTK_Class;
- case TypeRecordKind::Struct:
- return clang::TTK_Struct;
- case TypeRecordKind::Union:
- return clang::TTK_Union;
- case TypeRecordKind::Interface:
- return clang::TTK_Interface;
- case TypeRecordKind::Enum:
- return clang::TTK_Enum;
- default:
- lldbassert(false && "Invalid tag record kind!");
- return clang::TTK_Struct;
- }
-}
-
-static llvm::Optional<clang::CallingConv>
-TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
- using CC = llvm::codeview::CallingConvention;
- switch (conv) {
-
- case CC::NearC:
- case CC::FarC:
- return clang::CallingConv::CC_C;
- case CC::NearPascal:
- case CC::FarPascal:
- return clang::CallingConv::CC_X86Pascal;
- case CC::NearFast:
- case CC::FarFast:
- return clang::CallingConv::CC_X86FastCall;
- case CC::NearStdCall:
- case CC::FarStdCall:
- return clang::CallingConv::CC_X86StdCall;
- case CC::ThisCall:
- return clang::CallingConv::CC_X86ThisCall;
- case CC::NearVector:
- return clang::CallingConv::CC_X86VectorCall;
- default:
- return llvm::None;
- }
-}
-
-static Variable::RangeList
-MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
- llvm::ArrayRef<LocalVariableAddrGap> gaps) {
- lldb::addr_t start =
- index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
- lldb::addr_t end = start + range.Range;
-
- Variable::RangeList result;
- while (!gaps.empty()) {
- const LocalVariableAddrGap &gap = gaps.front();
-
- lldb::addr_t size = gap.GapStartOffset - start;
- result.Append(start, size);
- start += gap.Range;
- gaps = gaps.drop_front();
- }
-
- result.Append(start, end);
- return result;
-}
-
-static VariableInfo GetVariableInformation(PdbIndex &index,
- PdbCompilandSymId var_id,
- ModuleSP module,
- bool get_location_info) {
- VariableInfo result;
- CVSymbol sym = index.ReadSymbolRecord(var_id);
-
- if (sym.kind() == S_REGREL32) {
- RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
- cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
- result.type = reg.Type;
- result.name = reg.Name;
- if (get_location_info) {
- result.location =
- MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
- result.ranges.emplace();
- }
- return result;
- }
-
- if (sym.kind() == S_REGISTER) {
- RegisterSym reg(SymbolRecordKind::RegisterSym);
- cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
- result.type = reg.Index;
- result.name = reg.Name;
- if (get_location_info) {
- result.location =
- MakeEnregisteredLocationExpression(reg.Register, module);
- result.ranges.emplace();
- }
- return result;
- }
-
- if (sym.kind() == S_LOCAL) {
- LocalSym local(SymbolRecordKind::LocalSym);
- cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
- result.type = local.Type;
- result.name = local.Name;
-
- if (!get_location_info)
- return result;
-
- PdbCompilandSymId loc_specifier_id(var_id.modi,
- var_id.offset + sym.RecordData.size());
- CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
- if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
- DefRangeFramePointerRelSym loc(
- SymbolRecordKind::DefRangeFramePointerRelSym);
- cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
- loc_specifier_cvs, loc));
- // FIXME: The register needs to come from the S_FRAMEPROC symbol.
- result.location =
- MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module);
- result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
- } else {
- // FIXME: Handle other kinds
- llvm::APSInt value;
- value = 42;
- result.location = MakeConstantLocationExpression(
- TypeIndex::Int32(), index.tpi(), value, module);
- }
- return result;
- }
- llvm_unreachable("Symbol is not a local variable!");
- return result;
-}
-
void SymbolFileNativePDB::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance,
@@ -489,117 +319,12 @@ void SymbolFileNativePDB::InitializeObject() {
m_index->SetLoadAddress(m_obj_load_address);
m_index->ParseSectionContribs();
- TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
- m_clang = llvm::dyn_cast_or_null<ClangASTContext>(ts);
- m_importer = llvm::make_unique<ClangASTImporter>();
-
- PreprocessTpiStream();
- lldbassert(m_clang);
-}
-
-static llvm::Optional<CVTagRecord>
-GetNestedTagRecord(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 = 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 = 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::PreprocessTpiStream() {
- LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
-
- for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
- CVType type = types.getType(*ti);
- if (!IsTagRecord(type))
- continue;
-
- CVTagRecord tag = CVTagRecord::create(type);
- // 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;
- TypeIndex parent;
- const CVTagRecord &parent_cvt;
-
- llvm::Error visitKnownMember(CVMemberRecord &CVR,
- NestedTypeRecord &Record) override {
- llvm::Optional<CVTagRecord> tag =
- GetNestedTagRecord(Record, parent_cvt, index.tpi());
- if (!tag)
- return llvm::ErrorSuccess();
-
- parents[Record.Type] = parent;
- if (!tag->asTag().isForwardRef())
- return llvm::ErrorSuccess();
-
- llvm::Expected<TypeIndex> full_decl =
- index.tpi().findFullDeclForForwardRef(Record.Type);
- if (!full_decl) {
- llvm::consumeError(full_decl.takeError());
- return llvm::ErrorSuccess();
- }
- parents[*full_decl] = parent;
- return llvm::ErrorSuccess();
- }
- };
+ TypeSystem *ts = m_obj_file->GetModule()->GetTypeSystemForLanguage(
+ lldb::eLanguageTypeC_plus_plus);
+ if (ts)
+ ts->SetSymbolFile(this);
- CVType field_list = m_index->tpi().getType(tag.asTag().FieldList);
- ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
- llvm::Error error = visitMemberRecordStream(field_list.data(), process);
- if (error)
- llvm::consumeError(std::move(error));
- }
+ m_ast = llvm::make_unique<PdbAstBuilder>(*m_obj_file, *m_index);
}
uint32_t SymbolFileNativePDB::GetNumCompileUnits() {
@@ -620,7 +345,6 @@ uint32_t SymbolFileNativePDB::GetNumCompileUnits() {
Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
- clang::DeclContext *parent_decl_ctx = m_clang->GetTranslationUnitDecl();
if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32) {
// This is a function. It must be global. Creating the Function entry for
@@ -639,18 +363,13 @@ Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
lldbassert(block.Parent != 0);
PdbCompilandSymId parent_id(block_id.modi, block.Parent);
Block &parent_block = GetOrCreateBlock(parent_id);
-
lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
parent_block.AddChild(child_block);
- CompilerDeclContext cdc = GetDeclContextForUID(parent_block.GetID());
- parent_decl_ctx =
- static_cast<clang::DeclContext *>(cdc.GetOpaqueDeclContext());
- clang::BlockDecl *block_decl =
- m_clang->CreateBlockDeclaration(parent_decl_ctx);
+
+ m_ast->GetOrCreateBlockDecl(block_id);
m_blocks.insert({opaque_block_uid, child_block});
- m_uid_to_decl.insert({opaque_block_uid, block_decl});
return *child_block;
}
@@ -685,73 +404,7 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
comp_unit.AddFunction(func_sp);
- user_id_t opaque_func_uid = toOpaqueUid(func_id);
-
- clang::StorageClass storage = clang::SC_None;
- if (sym_record.kind() == S_LPROC32)
- storage = clang::SC_Static;
-
- // The function signature only tells us the number of types of arguments, but
- // not the names. So we need to iterate the symbol stream looking for the
- // corresponding symbol records to properly construct the AST.
- CVType sig_cvt;
- ProcedureRecord sig_record;
-
- sig_cvt = m_index->tpi().getType(proc.FunctionType);
- if (sig_cvt.kind() != LF_PROCEDURE)
- return func_sp;
- cantFail(
- TypeDeserializer::deserializeAs<ProcedureRecord>(sig_cvt, sig_record));
-
- CompilerDeclContext context = GetDeclContextContainingUID(opaque_func_uid);
-
- clang::DeclContext *decl_context =
- static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
- clang::FunctionDecl *function_decl = m_clang->CreateFunctionDeclaration(
- decl_context, proc.Name.str().c_str(),
- func_type->GetForwardCompilerType(), storage, false);
-
- lldbassert(m_uid_to_decl.count(opaque_func_uid) == 0);
- m_uid_to_decl[opaque_func_uid] = function_decl;
-
- CVSymbolArray scope = limitSymbolArrayToScope(
- cci->m_debug_stream.getSymbolArray(), func_id.offset);
-
- uint32_t params_remaining = sig_record.getParameterCount();
- auto begin = scope.begin();
- auto end = scope.end();
- std::vector<clang::ParmVarDecl *> params;
- while (begin != end && params_remaining > 0) {
- CVSymbol sym = *begin;
- switch (sym.kind()) {
- case S_REGREL32:
- case S_REGISTER:
- case S_LOCAL:
- break;
- case S_BLOCK32:
- params_remaining = 0;
- continue;
- default:
- ++begin;
- continue;
- }
- PdbCompilandSymId param_uid(func_id.modi, begin.offset());
- VariableInfo var_info = GetVariableInformation(
- *m_index, param_uid, GetObjectFile()->GetModule(), false);
-
- TypeSP type_sp = GetOrCreateType(var_info.type);
- clang::ParmVarDecl *param = m_clang->CreateParameterDeclaration(
- function_decl, var_info.name.str().c_str(),
- type_sp->GetForwardCompilerType(), clang::SC_None);
- lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
-
- m_uid_to_decl[toOpaqueUid(param_uid)] = param;
- params.push_back(param);
- --params_remaining;
- ++begin;
- }
- if (!params.empty())
- m_clang->SetFunctionParameters(function_decl, params.data(), params.size());
+ m_ast->GetOrCreateFunctionDecl(func_id);
return func_sp;
}
@@ -780,76 +433,48 @@ SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
}
lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
- const ModifierRecord &mr) {
+ const ModifierRecord &mr,
+ CompilerType ct) {
TpiStream &stream = m_index->tpi();
- TypeSP t = GetOrCreateType(mr.ModifiedType);
- CompilerType ct = t->GetForwardCompilerType();
- if ((mr.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
- ct = ct.AddConstModifier();
- if ((mr.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)
- ct = ct.AddVolatileModifier();
std::string name;
if (mr.ModifiedType.isSimple())
name = GetSimpleTypeName(mr.ModifiedType.getSimpleKind());
else
name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
Declaration decl;
- return std::make_shared<Type>(toOpaqueUid(type_id), m_clang->GetSymbolFile(),
- ConstString(name), t->GetByteSize(), nullptr,
+ lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
+
+ return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name),
+ modified_type->GetByteSize(), nullptr,
LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
ct, Type::eResolveStateFull);
}
-lldb::TypeSP SymbolFileNativePDB::CreatePointerType(
- PdbTypeSymId type_id, const llvm::codeview::PointerRecord &pr) {
+lldb::TypeSP
+SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
+ const llvm::codeview::PointerRecord &pr,
+ CompilerType ct) {
TypeSP pointee = GetOrCreateType(pr.ReferentType);
if (!pointee)
return nullptr;
- CompilerType pointee_ct = pointee->GetForwardCompilerType();
- lldbassert(pointee_ct);
- Declaration decl;
if (pr.isPointerToMember()) {
MemberPointerInfo mpi = pr.getMemberInfo();
- TypeSP class_type = GetOrCreateType(mpi.ContainingType);
-
- CompilerType ct = ClangASTContext::CreateMemberPointerType(
- class_type->GetLayoutCompilerType(), pointee_ct);
-
- return std::make_shared<Type>(
- toOpaqueUid(type_id), m_clang->GetSymbolFile(), ConstString(),
- pr.getSize(), nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
- Type::eResolveStateFull);
+ GetOrCreateType(mpi.ContainingType);
}
- CompilerType pointer_ct = pointee_ct;
- if (pr.getMode() == PointerMode::LValueReference)
- pointer_ct = pointer_ct.GetLValueReferenceType();
- else if (pr.getMode() == PointerMode::RValueReference)
- pointer_ct = pointer_ct.GetRValueReferenceType();
- else
- pointer_ct = pointer_ct.GetPointerType();
-
- if ((pr.getOptions() & PointerOptions::Const) != PointerOptions::None)
- pointer_ct = pointer_ct.AddConstModifier();
-
- if ((pr.getOptions() & PointerOptions::Volatile) != PointerOptions::None)
- pointer_ct = pointer_ct.AddVolatileModifier();
-
- if ((pr.getOptions() & PointerOptions::Restrict) != PointerOptions::None)
- pointer_ct = pointer_ct.AddRestrictModifier();
-
- return std::make_shared<Type>(toOpaqueUid(type_id), m_clang->GetSymbolFile(),
- ConstString(), pr.getSize(), nullptr,
- LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
- pointer_ct, Type::eResolveStateFull);
+ Declaration decl;
+ return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(),
+ pr.getSize(), nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct,
+ Type::eResolveStateFull);
}
-lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti) {
+lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
+ CompilerType ct) {
uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
if (ti == TypeIndex::NullptrT()) {
- CompilerType ct = m_clang->GetBasicType(eBasicTypeNullPtr);
Declaration decl;
return std::make_shared<Type>(
uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID,
@@ -858,8 +483,6 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti) {
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
- CompilerType ct = direct_sp->GetFullCompilerType();
- ct = ct.GetPointerType();
uint32_t pointer_size = 0;
switch (ti.getSimpleMode()) {
case SimpleTypeMode::FarPointer32:
@@ -874,253 +497,101 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti) {
return nullptr;
}
Declaration decl;
- return std::make_shared<Type>(uid, m_clang->GetSymbolFile(), ConstString(),
- pointer_size, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct,
- Type::eResolveStateFull);
+ return std::make_shared<Type>(
+ uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
}
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
return nullptr;
- lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind());
- if (bt == lldb::eBasicTypeInvalid)
- return nullptr;
- CompilerType ct = m_clang->GetBasicType(bt);
size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
-
llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
Declaration decl;
- return std::make_shared<Type>(uid, m_clang->GetSymbolFile(),
- ConstString(type_name), size, nullptr,
- LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
- ct, Type::eResolveStateFull);
+ return std::make_shared<Type>(uid, this, ConstString(type_name), size,
+ nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
+ decl, ct, Type::eResolveStateFull);
}
-static std::string RenderDemanglerNode(llvm::ms_demangle::Node *n) {
- OutputStream OS;
- initializeOutputStream(nullptr, nullptr, OS, 1024);
- n->output(OS, llvm::ms_demangle::OF_Default);
- OS << '\0';
- return {OS.getBuffer()};
-}
-
-static bool
-AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) {
- for (llvm::ms_demangle::Node *n : scopes) {
- auto *idn = static_cast<llvm::ms_demangle::IdentifierNode *>(n);
- if (idn->TemplateParams)
- return true;
- }
- return false;
-}
-
-std::pair<clang::DeclContext *, std::string>
-SymbolFileNativePDB::CreateDeclInfoForType(const TagRecord &record,
- TypeIndex ti) {
- // FIXME: Move this to GetDeclContextContainingUID.
-
+static std::string GetUnqualifiedTypeName(const TagRecord &record) {
llvm::ms_demangle::Demangler demangler;
StringView sv(record.UniqueName.begin(), record.UniqueName.size());
llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
llvm::ms_demangle::IdentifierNode *idn =
ttn->QualifiedName->getUnqualifiedIdentifier();
- std::string uname = RenderDemanglerNode(idn);
-
- llvm::ms_demangle::NodeArrayNode *name_components =
- ttn->QualifiedName->Components;
- llvm::ArrayRef<llvm::ms_demangle::Node *> scopes(name_components->Nodes,
- name_components->Count - 1);
-
- clang::DeclContext *context = m_clang->GetTranslationUnitDecl();
-
- // 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()) {
- if (scopes.empty())
- return {context, uname};
-
- // If there is no parent in the debug info, but some of the scopes have
- // template params, then this is a case of bad debug info. See, for
- // example, llvm.org/pr39607. We don't want to create an ambiguity between
- // a NamespaceDecl and a CXXRecordDecl, so instead we create a class at
- // global scope with the fully qualified name.
- if (AnyScopesHaveTemplateParams(scopes))
- return {context, record.Name};
-
- for (llvm::ms_demangle::Node *scope : scopes) {
- auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope);
- std::string str = RenderDemanglerNode(nii);
- context = m_clang->GetUniqueNamespaceDeclaration(str.c_str(), context);
- }
- return {context, uname};
- }
-
- // Otherwise, all we need to do is get the parent type of this type and
- // 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.
- TypeSP parent = GetOrCreateType(parent_iter->second);
- if (!parent)
- return {context, uname};
- CompilerType parent_ct = parent->GetForwardCompilerType();
- clang::QualType qt = ClangUtil::GetCanonicalQualType(parent_ct);
- context = clang::TagDecl::castToDeclContext(qt->getAsTagDecl());
- return {context, uname};
+ return idn->toString();
}
-lldb::TypeSP SymbolFileNativePDB::CreateClassStructUnion(
- PdbTypeSymId type_id, const llvm::codeview::TagRecord &record, size_t size,
- clang::TagTypeKind ttk, clang::MSInheritanceAttr::Spelling inheritance) {
-
- clang::DeclContext *decl_context = nullptr;
- std::string uname;
- std::tie(decl_context, uname) = CreateDeclInfoForType(record, type_id.index);
-
- lldb::AccessType access =
- (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
+lldb::TypeSP
+SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
+ const TagRecord &record,
+ size_t size, CompilerType ct) {
- ClangASTMetadata metadata;
- metadata.SetUserID(toOpaqueUid(type_id));
- metadata.SetIsDynamicCXXType(false);
-
- CompilerType ct =
- m_clang->CreateRecordType(decl_context, access, uname.c_str(), ttk,
- lldb::eLanguageTypeC_plus_plus, &metadata);
-
- lldbassert(ct.IsValid());
-
- clang::CXXRecordDecl *record_decl =
- m_clang->GetAsCXXRecordDecl(ct.GetOpaqueQualType());
- lldbassert(record_decl);
-
- clang::MSInheritanceAttr *attr = clang::MSInheritanceAttr::CreateImplicit(
- *m_clang->getASTContext(), inheritance);
- record_decl->addAttr(attr);
-
- ClangASTContext::StartTagDeclarationDefinition(ct);
-
- // Even if it's possible, don't complete it at this point. Just mark it
- // forward resolved, and if/when LLDB needs the full definition, it can
- // ask us.
- ClangASTContext::SetHasExternalStorage(ct.GetOpaqueQualType(), true);
+ std::string uname = GetUnqualifiedTypeName(record);
// FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
Declaration decl;
- return std::make_shared<Type>(toOpaqueUid(type_id), m_clang->GetSymbolFile(),
- ConstString(uname), size, nullptr,
- LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
- ct, Type::eResolveStateForward);
+ return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname),
+ size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct,
+ Type::eResolveStateForward);
}
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
- const ClassRecord &cr) {
- clang::TagTypeKind ttk = TranslateUdtKind(cr);
-
- clang::MSInheritanceAttr::Spelling inheritance =
- GetMSInheritance(m_index->tpi().typeCollection(), cr);
- return CreateClassStructUnion(type_id, cr, cr.getSize(), ttk, inheritance);
+ const ClassRecord &cr,
+ CompilerType ct) {
+ return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
}
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
- const UnionRecord &ur) {
- return CreateClassStructUnion(
- type_id, ur, ur.getSize(), clang::TTK_Union,
- clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance);
+ const UnionRecord &ur,
+ CompilerType ct) {
+ return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
}
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
- const EnumRecord &er) {
- clang::DeclContext *decl_context = nullptr;
- std::string uname;
- std::tie(decl_context, uname) = CreateDeclInfoForType(er, type_id.index);
+ const EnumRecord &er,
+ CompilerType ct) {
+ std::string uname = GetUnqualifiedTypeName(er);
Declaration decl;
TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
- CompilerType enum_ct = m_clang->CreateEnumerationType(
- uname.c_str(), decl_context, decl, underlying_type->GetFullCompilerType(),
- er.isScoped());
- ClangASTContext::StartTagDeclarationDefinition(enum_ct);
- ClangASTContext::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true);
-
- // We're just going to forward resolve this for now. We'll complete
- // it only if the user requests.
return std::make_shared<lldb_private::Type>(
- toOpaqueUid(type_id), m_clang->GetSymbolFile(), ConstString(uname),
+ toOpaqueUid(type_id), this, ConstString(uname),
underlying_type->GetByteSize(), nullptr, LLDB_INVALID_UID,
- lldb_private::Type::eEncodingIsUID, decl, enum_ct,
+ lldb_private::Type::eEncodingIsUID, decl, ct,
lldb_private::Type::eResolveStateForward);
}
TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
- const ArrayRecord &ar) {
+ const ArrayRecord &ar,
+ CompilerType ct) {
TypeSP element_type = GetOrCreateType(ar.ElementType);
- uint64_t element_count = ar.Size / element_type->GetByteSize();
-
- CompilerType element_ct = element_type->GetFullCompilerType();
-
- CompilerType array_ct =
- m_clang->CreateArrayType(element_ct, element_count, false);
Declaration decl;
TypeSP array_sp = std::make_shared<lldb_private::Type>(
- toOpaqueUid(type_id), m_clang->GetSymbolFile(), ConstString(), ar.Size,
- nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
- array_ct, lldb_private::Type::eResolveStateFull);
+ toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr,
+ LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
+ lldb_private::Type::eResolveStateFull);
array_sp->SetEncodingType(element_type.get());
return array_sp;
}
TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
- const ProcedureRecord &pr) {
- TpiStream &stream = m_index->tpi();
- CVType args_cvt = stream.getType(pr.ArgumentList);
- ArgListRecord args;
- llvm::cantFail(
- TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
-
- llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices);
- bool is_variadic = IsCVarArgsFunction(arg_indices);
- if (is_variadic)
- arg_indices = arg_indices.drop_back();
-
- std::vector<CompilerType> arg_list;
- arg_list.reserve(arg_list.size());
-
- for (TypeIndex arg_index : arg_indices) {
- TypeSP arg_sp = GetOrCreateType(arg_index);
- if (!arg_sp)
- return nullptr;
- arg_list.push_back(arg_sp->GetFullCompilerType());
- }
-
- TypeSP return_type_sp = GetOrCreateType(pr.ReturnType);
- if (!return_type_sp)
- return nullptr;
-
- llvm::Optional<clang::CallingConv> cc =
- TranslateCallingConvention(pr.CallConv);
- if (!cc)
- return nullptr;
-
- CompilerType return_ct = return_type_sp->GetFullCompilerType();
- CompilerType func_sig_ast_type = m_clang->CreateFunctionType(
- return_ct, arg_list.data(), arg_list.size(), is_variadic, 0, *cc);
-
+ const ProcedureRecord &pr,
+ CompilerType ct) {
Declaration decl;
return std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
- lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type,
+ lldb_private::Type::eEncodingIsUID, decl, ct,
lldb_private::Type::eResolveStateFull);
}
-TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id) {
+TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
if (type_id.index.isSimple())
- return CreateSimpleType(type_id.index);
+ return CreateSimpleType(type_id.index, ct);
TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
CVType cvt = stream.getType(type_id.index);
@@ -1129,44 +600,44 @@ TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id) {
ModifierRecord modifier;
llvm::cantFail(
TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
- return CreateModifierType(type_id, modifier);
+ return CreateModifierType(type_id, modifier, ct);
}
if (cvt.kind() == LF_POINTER) {
PointerRecord pointer;
llvm::cantFail(
TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
- return CreatePointerType(type_id, pointer);
+ return CreatePointerType(type_id, pointer, ct);
}
if (IsClassRecord(cvt.kind())) {
ClassRecord cr;
llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
- return CreateTagType(type_id, cr);
+ return CreateTagType(type_id, cr, ct);
}
if (cvt.kind() == LF_ENUM) {
EnumRecord er;
llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
- return CreateTagType(type_id, er);
+ return CreateTagType(type_id, er, ct);
}
if (cvt.kind() == LF_UNION) {
UnionRecord ur;
llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
- return CreateTagType(type_id, ur);
+ return CreateTagType(type_id, ur, ct);
}
if (cvt.kind() == LF_ARRAY) {
ArrayRecord ar;
llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
- return CreateArrayType(type_id, ar);
+ return CreateArrayType(type_id, ar, ct);
}
if (cvt.kind() == LF_PROCEDURE) {
ProcedureRecord pr;
llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
- return CreateProcedureType(type_id, pr);
+ return CreateProcedureType(type_id, pr, ct);
}
return nullptr;
@@ -1200,7 +671,10 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
}
PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
- TypeSP result = CreateType(best_decl_id);
+
+ clang::QualType qt = m_ast->GetOrCreateType(best_decl_id);
+
+ TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt));
if (!result)
return nullptr;
@@ -1211,15 +685,6 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
if (full_decl_uid)
m_types[toOpaqueUid(type_id)] = result;
- if (IsTagRecord(best_decl_id, m_index->tpi())) {
- clang::TagDecl *record_decl =
- m_clang->GetAsTagDecl(result->GetForwardCompilerType());
- lldbassert(record_decl);
-
- m_uid_to_decl[best_uid] = record_decl;
- m_decl_to_status[record_decl] =
- DeclStatus(best_uid, Type::eResolveStateForward);
- }
return result;
}
@@ -1631,11 +1096,7 @@ size_t SymbolFileNativePDB::ParseFunctionBlocks(const SymbolContext &sc) {
return 1;
}
-void SymbolFileNativePDB::DumpClangAST(Stream &s) {
- if (!m_clang)
- return;
- m_clang->Dump(s);
-}
+void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); }
uint32_t SymbolFileNativePDB::FindGlobalVariables(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
@@ -1764,8 +1225,7 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
PdbCompilandSymId var_id,
bool is_param) {
ModuleSP module = GetObjectFile()->GetModule();
- VariableInfo var_info =
- GetVariableInformation(*m_index, var_id, module, true);
+ VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module);
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
@@ -1782,20 +1242,8 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
comp_unit_sp.get(), *var_info.ranges, &decl, *var_info.location, false,
false, false);
- CompilerDeclContext cdc = GetDeclContextForUID(toOpaqueUid(scope_id));
- clang::DeclContext *decl_ctx =
- static_cast<clang::DeclContext *>(cdc.GetOpaqueDeclContext());
-
- // Parameter info should have already been added to the AST.
- if (!is_param) {
- clang::QualType qt =
- ClangUtil::GetCanonicalQualType(type_sp->GetForwardCompilerType());
-
- clang::VarDecl *var_decl =
- m_clang->CreateVariableDeclaration(decl_ctx, name.c_str(), qt);
- lldbassert(m_uid_to_decl.count(toOpaqueUid(var_id)) == 0);
- m_uid_to_decl[toOpaqueUid(var_id)] = var_decl;
- }
+ if (!is_param)
+ m_ast->GetOrCreateLocalVariableDecl(scope_id, var_id);
m_local_variables[toOpaqueUid(var_id)] = var_sp;
return var_sp;
@@ -1919,44 +1367,25 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
}
CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
- auto iter = m_uid_to_decl.find(uid);
- if (iter == m_uid_to_decl.end())
- return CompilerDecl();
+ clang::Decl *decl = m_ast->GetOrCreateDeclForUid(PdbSymUid(uid));
- return {m_clang, iter->second};
+ return m_ast->ToCompilerDecl(*decl);
}
CompilerDeclContext
SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
- CompilerDecl compiler_decl = GetDeclForUID(uid);
- clang::Decl *decl = static_cast<clang::Decl *>(compiler_decl.GetOpaqueDecl());
- return {m_clang, clang::Decl::castToDeclContext(decl)};
+ clang::DeclContext *context =
+ m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid));
+ if (!context)
+ return {};
+
+ return m_ast->ToCompilerDeclContext(*context);
}
CompilerDeclContext
SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
- // FIXME: This should look up the uid, decide if it's a symbol or a type, and
- // depending which it is, find the appropriate DeclContext. Possibilities:
- // For classes and typedefs:
- // * Function
- // * Namespace
- // * Global
- // * Block
- // * Class
- // For field list members:
- // * Class
- // For variables:
- // * Function
- // * Namespace
- // * Global
- // * Block
- // For functions:
- // * Namespace
- // * Global
- // * Class
- //
- // It is an error to call this function with a uid for any other symbol type.
- return {m_clang, m_clang->GetTranslationUnitDecl()};
+ clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid));
+ return m_ast->ToCompilerDeclContext(*context);
}
Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -1987,73 +1416,10 @@ SymbolFileNativePDB::GetDynamicArrayInfoForUID(
bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
- // If this is not in our map, it's an error.
- clang::TagDecl *tag_decl = m_clang->GetAsTagDecl(compiler_type);
- lldbassert(tag_decl);
- auto status_iter = m_decl_to_status.find(tag_decl);
- lldbassert(status_iter != m_decl_to_status.end());
-
- // If it's already complete, just return.
- DeclStatus &status = status_iter->second;
- if (status.status == Type::eResolveStateFull)
- return true;
+ clang::QualType qt =
+ clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
- PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym();
-
- lldbassert(IsTagRecord(type_id, m_index->tpi()));
-
- ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
- false);
-
- // In CreateAndCacheType, we already go out of our way to resolve forward
- // ref UDTs to full decls, and the uids we vend out always refer to full
- // decls if a full decl exists in the debug info. So if we don't have a full
- // decl here, it means one doesn't exist in the debug info, and we can't
- // complete the type.
- CVType cvt = m_index->tpi().getType(TypeIndex(type_id.index));
- if (IsForwardRefUdt(cvt))
- return false;
-
- auto types_iter = m_types.find(status.uid);
- lldbassert(types_iter != m_types.end());
-
- if (cvt.kind() == LF_MODIFIER) {
- TypeIndex unmodified_type = LookThroughModifierRecord(cvt);
- cvt = m_index->tpi().getType(unmodified_type);
- // LF_MODIFIERS usually point to forward decls, so this is the one case
- // where we won't have been able to resolve a forward decl to a full decl
- // earlier on. So we need to do that now.
- if (IsForwardRefUdt(cvt)) {
- llvm::Expected<TypeIndex> expected_full_ti =
- m_index->tpi().findFullDeclForForwardRef(unmodified_type);
- if (!expected_full_ti) {
- llvm::consumeError(expected_full_ti.takeError());
- return false;
- }
- cvt = m_index->tpi().getType(*expected_full_ti);
- lldbassert(!IsForwardRefUdt(cvt));
- unmodified_type = *expected_full_ti;
- }
- type_id = PdbTypeSymId(unmodified_type, false);
- }
- TypeIndex field_list_ti = GetFieldListIndex(cvt);
- CVType field_list_cvt = m_index->tpi().getType(field_list_ti);
- if (field_list_cvt.kind() != LF_FIELDLIST)
- return false;
-
- // Visit all members of this class, then perform any finalization necessary
- // to complete the class.
- UdtRecordCompleter completer(type_id, compiler_type, *tag_decl, *this);
- auto error =
- llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer);
- completer.complete();
-
- status.status = Type::eResolveStateFull;
- if (!error)
- return true;
-
- llvm::consumeError(std::move(error));
- return false;
+ return m_ast->CompleteType(qt);
}
size_t SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,