From d16203e98611983aa870ceddd751bc8b2ecc65fa Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 16 Aug 2019 17:34:55 -0700 Subject: [PATCH 1/6] DWARFImporter: Allow filtering type lookups by containing module. This currently does not work for types defined in a submodule because Swift only keeps track of the toplevel module. --- .../dwarfimporter/C/Inputs/module.modulemap | 6 +- .../swift/dwarfimporter/C/Inputs/submodule.h | 3 + .../C/TestSwiftDWARFImporterC.py | 24 ++++--- .../lang/swift/dwarfimporter/C/main.swift | 3 + .../Objective-C/Inputs/module.modulemap | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 64 +++++++++++-------- .../DWARF/SymbolFileDWARFDebugMap.cpp | 16 +++++ .../DWARF/SymbolFileDWARFDebugMap.h | 2 + source/Symbol/SwiftASTContext.cpp | 59 +++++++++++------ 9 files changed, 121 insertions(+), 58 deletions(-) create mode 100644 packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/submodule.h diff --git a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/module.modulemap b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/module.modulemap index 7356121d8134..822cd8009bcc 100644 --- a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/module.modulemap +++ b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/module.modulemap @@ -1,4 +1,8 @@ module CModule { header "c-header.h" export * -} \ No newline at end of file + module SubModule { + header "submodule.h" + export * + } +} diff --git a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/submodule.h b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/submodule.h new file mode 100644 index 000000000000..4f1840af805a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/Inputs/submodule.h @@ -0,0 +1,3 @@ +struct FromSubmodule { + unsigned x, y, z; +}; diff --git a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py index ee3eb8c14eae..6c06a644621f 100644 --- a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py +++ b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py @@ -26,7 +26,7 @@ def build(self): inputs = self.getSourcePath('Inputs') lldbutil.mkdir_p(include) import shutil - for f in ['module.modulemap', 'c-header.h']: + for f in ['module.modulemap', 'c-header.h', 'submodule.h']: shutil.copyfile(os.path.join(inputs, f), os.path.join(include, f)) super(TestSwiftDWARFImporterC, self).build() @@ -52,14 +52,18 @@ def test_dwarf_importer(self): lldbutil.check_variable(self, target.FindFirstGlobalVariable("point"), typename='__ObjC.Point', num_children=2) - self.expect("fr v point", substrs=["x = 1", "y = 2"]) - self.expect("fr v point", substrs=["x = 1", "y = 2"]) - self.expect("fr v enumerator", substrs=[".yellow"]) - self.expect("fr v pureSwiftStruct", substrs=["pure swift"]) - self.expect("fr v swiftStructCMember", - substrs=["x = 3", "y = 4", "swift struct c member"]) - self.expect("fr v typedef", substrs=["x = 5", "y = 6"]) - self.expect("fr v union", substrs=["(DoubleLongUnion)", "long_val = 42"]) + self.expect("ta v point", substrs=["x = 1", "y = 2"]) + self.expect("ta v enumerator", substrs=[".yellow"]) + self.expect("ta v pureSwiftStruct", substrs=["pure swift"]) + self.expect("ta v swiftStructCMember", + substrs=["point", "x = 3", "y = 4", + # FIXME: + # "sub", "x = 1", "y = 2", "z = 3", + "swift struct c member"]) + self.expect("ta v typedef", substrs=["x = 5", "y = 6"]) + self.expect("ta v union", substrs=["(DoubleLongUnion)", "long_val = 42"]) + self.expect("ta v fromSubmodule", + substrs=["(FromSubmodule)", "x = 1", "y = 2", "z = 3"]) process.Clear() target.Clear() lldb.SBDebugger.MemoryPressureDetected() @@ -79,7 +83,7 @@ def test_negative(self): lldbutil.check_variable(self, target.FindFirstGlobalVariable("point"), typename="Point", num_children=2) - self.expect("fr v point", substrs=["x = 1", "y = 2"]) + self.expect("ta v point", substrs=["x = 1", "y = 2"]) found = False logfile = open(log, "r") diff --git a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/main.swift b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/main.swift index 2ea1f732fe6b..45ac92a6b7b0 100644 --- a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/main.swift +++ b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/main.swift @@ -14,12 +14,14 @@ let pureSwiftStruct = SwiftStruct() struct SwiftStructCMember { let point = Point(x: 3, y: 4) + let sub = FromSubmodule(x: 1, y: 2, z: 3) let name = "swift struct c member" } let swiftStructCMember = SwiftStructCMember() let typedef = TPoint(x: 5, y: 6) let union = DoubleLongUnion(long_val: 42) +let fromSubmodule = FromSubmodule(x: 1, y: 2, z: 3) use(pureSwift) // break here use(point) @@ -28,3 +30,4 @@ use(pureSwiftStruct) use(swiftStructCMember) use(typedef) use(union) +use(fromSubmodule) diff --git a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/Objective-C/Inputs/module.modulemap b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/Objective-C/Inputs/module.modulemap index a9ef2ed15c11..2f37bc7aad4f 100644 --- a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/Objective-C/Inputs/module.modulemap +++ b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/Objective-C/Inputs/module.modulemap @@ -1,4 +1,4 @@ module ObjCModule { header "objc-header.h" export * -} \ No newline at end of file +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 57934161e325..b905d7b342bf 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2522,37 +2522,45 @@ size_t SymbolFileDWARF::FindTypes(const std::vector &context, m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - size_t num_matches = 0; - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (die) { - // LLDB never searches for Swift type definitions by context. - if (die.GetCU()->GetLanguageType() == eLanguageTypeSwift) - continue; - - std::vector die_context; - die.GetDeclContext(die_context); - if (die_context != context) - continue; - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - ++num_matches; - } - } else { - m_index->ReportInvalidDIEOffset(die_ref.die_offset, - name.GetStringRef()); + size_t num_matches = 0; + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); + + if (die) { + // LLDB never searches for Swift type definitions by context. + if (die.GetCU()->GetLanguageType() == eLanguageTypeSwift) + continue; + + std::vector die_context; + die.GetDeclContext(die_context); + if (die_context != context) + continue; + + Type *matching_type = ResolveType(die, true, true); + if (matching_type) { + // We found a type pointer, now find the shared pointer form our type + // list + types.InsertUnique(matching_type->shared_from_this()); + ++num_matches; } + } else { + m_index->ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef()); } - return num_matches; } - return 0; + + // Next search through the reachable Clang modules. This only applies for + // DWARF objects compiled with -gmodules that haven't been processed by + // dsymutil. + UpdateExternalModuleListIfNeeded(); + + for (const auto &pair : m_external_type_modules) + if (ModuleSP external_module_sp = pair.second) { + SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); + if (sym_vendor) + num_matches += sym_vendor->FindTypes(context, true, types); + } + return num_matches; } CompilerDeclContext diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 7ca6b7b11c0c..1c47197ef410 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1197,6 +1197,22 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes( return types.GetSize() - initial_types_size; } +size_t +SymbolFileDWARFDebugMap::FindTypes(const std::vector &context, + bool append, TypeMap &types) { + if (!append) + types.Clear(); + + const uint32_t initial_types_size = types.GetSize(); + + ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { + oso_dwarf->FindTypes(context, true, types); + return false; + }); + + return types.GetSize() - initial_types_size; +} + // // uint32_t // SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index f958d86d03b2..b0120eba7cc6 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -121,6 +121,8 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile { bool append, uint32_t max_matches, llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; + size_t FindTypes(const std::vector &context, + bool append, lldb_private::TypeMap &types) override; lldb_private::CompilerDeclContext FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; diff --git a/source/Symbol/SwiftASTContext.cpp b/source/Symbol/SwiftASTContext.cpp index 60af19ffcf96..ab10b184d756 100644 --- a/source/Symbol/SwiftASTContext.cpp +++ b/source/Symbol/SwiftASTContext.cpp @@ -3193,8 +3193,8 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { SwiftDWARFImporterDelegate(SwiftASTContext &swift_ast_ctx) : m_swift_ast_ctx(swift_ast_ctx) {} - void lookupValue(StringRef name, - llvm::Optional kind, + void lookupValue(StringRef name, llvm::Optional kind, + StringRef inModule, llvm::SmallVectorImpl &results) override { std::vector decl_context; ConstString name_cs(name); @@ -3208,21 +3208,41 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { // Find the type in the debug info. TypeList clang_types; - const bool exact_match = true; - const uint32_t max_matches = UINT32_MAX; - llvm::DenseSet searched_symbol_files; - if (!module->FindTypes(name_cs, exact_match, max_matches, - searched_symbol_files, clang_types)) - return; - SymbolFile *sym_file = m_swift_ast_ctx.GetSymbolFile(); - if (!sym_file) - return; - // Filter out non-Clang types. - auto *clang_ctx = llvm::dyn_cast_or_null( - sym_file->GetTypeSystemForLanguage(eLanguageTypeObjC)); - if (!clang_ctx) - return; + // Perform a lookup in a specific module, if requested. + if (!inModule.empty()) { + TypeMap type_map; + std::vector decl_context; + ConstString mod_name(inModule); + ConstString type_name(name); + // There's a bit of an impedance mismatch between the + // interfaces, Swift passes in either inModule (when looking up + // an inner Clang type) or kind (when coming through + // ASTDemangler), but it would be much more efficient if we had + // both. Alternatively, adding a wildcard CompilerContextKind + // would also save us from doing reedundant lookups here. + CompilerContextKind cc_kinds[] = { + CompilerContextKind::Class, CompilerContextKind::Structure, + CompilerContextKind::Union, CompilerContextKind::Enumeration, + CompilerContextKind::Typedef}; + for (auto cc_kind : cc_kinds) + if (module->GetSymbolVendor()->FindTypes( + {{CompilerContextKind::Module, mod_name}, {cc_kind, type_name}}, + true, type_map)) + break; + type_map.ForEach([&](lldb::TypeSP &type_sp) { + clang_types.Insert(type_sp); + return true; + }); + } else { + // Search globally. + const bool exact_match = true; + const uint32_t max_matches = UINT32_MAX; + llvm::DenseSet searched_symbol_files; + module->FindTypes(name_cs, exact_match, max_matches, + searched_symbol_files, clang_types); + } + clang::FileSystemOptions file_system_options; clang::FileManager file_manager(file_system_options); for (unsigned i = 0; i < clang_types.GetSize(); ++i) { @@ -3236,12 +3256,15 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { // Realize the full type. CompilerType compiler_type = clang_type_sp->GetFullCompilerType(); - // Import the type into the DWARFImporter's context. - clang::ASTContext &to_ctx = clang_importer->getClangASTContext(); + + // Filter our non-Clang types. auto *type_system = llvm::dyn_cast_or_null( compiler_type.GetTypeSystem()); if (!type_system) continue; + + // Import the type into the DWARFImporter's context. + clang::ASTContext &to_ctx = clang_importer->getClangASTContext(); clang::ASTContext *from_ctx = type_system->getASTContext(); if (!from_ctx) continue; From b0480db98b9bfb7453e01d38358c57989bac0494 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Wed, 21 Aug 2019 14:54:32 -0700 Subject: [PATCH 2/6] [Symbols] Sync dSYMForUUID code with upstream. These are now the defaults, no need to specify explicitly. --- source/Host/macosx/Symbols.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp index 2ce55076eac2..ebdbba76571e 100644 --- a/source/Host/macosx/Symbols.cpp +++ b/source/Host/macosx/Symbols.cpp @@ -570,12 +570,10 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec, StreamString command; if (!uuid_str.empty()) - command.Printf("%s --ignoreNegativeCache --copyExecutable --databases " - "bursar.apple.com,uuidsymmap.apple.com %s", + command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_str.c_str()); else if (file_path[0] != '\0') - command.Printf("%s --ignoreNegativeCache --copyExecutable --databases " - "bursar.apple.com,uuidsymmap.apple.com %s", + command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path); if (!command.GetString().empty()) { From cf2c4543a7d4d773a976b3434be5f59bf4221351 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 21 Aug 2019 18:06:56 +0000 Subject: [PATCH 3/6] Generalize FindTypes with CompilerContext to support fuzzy lookup This patch generalizes the FindTypes with CompilerContext interface to support looking up a type of unknown kind by name, as well as looking up a type inside an unspecified submodule. These features are motivated by the Swift branch, but are fully tested via unit tests and lldb-test on llvm.org. Specifically, this patch adds an AnyModule and an AnyType CompilerContext kind. Differential Revision: https://reviews.llvm.org/D66507 rdar://problem/54471165 git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@369555 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit 907acfbf6d86b67a0779de21a7ae98863a6a54e3) --- include/lldb/Symbol/SymbolFile.h | 4 +- include/lldb/Symbol/Type.h | 20 ++++--- include/lldb/lldb-private-enumerations.h | 28 ++++++---- lit/SymbolFile/DWARF/compilercontext.ll | 49 +++++++++++++++++ .../Breakpad/SymbolFileBreakpad.cpp | 5 +- .../SymbolFile/Breakpad/SymbolFileBreakpad.h | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 2 +- source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 32 +++++------- source/Plugins/SymbolFile/DWARF/DWARFDIE.h | 4 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 10 ++-- .../SymbolFile/DWARF/SymbolFileDWARF.h | 2 +- .../NativePDB/SymbolFileNativePDB.cpp | 5 +- .../NativePDB/SymbolFileNativePDB.h | 2 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 5 +- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h | 2 +- source/Symbol/SymbolFile.cpp | 2 +- source/Symbol/Type.cpp | 43 +++++++++++++-- tools/lldb-test/lldb-test.cpp | 52 ++++++++++++++++++- unittests/Symbol/TestType.cpp | 44 ++++++++++++++++ 19 files changed, 245 insertions(+), 68 deletions(-) create mode 100644 lit/SymbolFile/DWARF/compilercontext.ll diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h index 86b0c619046f..a3a51bd944cb 100644 --- a/include/lldb/Symbol/SymbolFile.h +++ b/include/lldb/Symbol/SymbolFile.h @@ -199,8 +199,8 @@ class SymbolFile : public PluginInterface { bool append, uint32_t max_matches, llvm::DenseSet &searched_symbol_files, TypeMap &types); - virtual size_t FindTypes(const std::vector &context, - bool append, TypeMap &types); + virtual size_t FindTypes(llvm::ArrayRef pattern, bool append, + TypeMap &types); virtual void GetMangledNamesForFunction(const std::string &scope_qualified_name, diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h index 7ed68bf1ded3..32b732861be2 100644 --- a/include/lldb/Symbol/Type.h +++ b/include/lldb/Symbol/Type.h @@ -22,24 +22,28 @@ #include namespace lldb_private { -//---------------------------------------------------------------------- -// CompilerContext allows an array of these items to be passed to perform -// detailed lookups in SymbolVendor and SymbolFile functions. -//---------------------------------------------------------------------- + +/// CompilerContext allows an array of these items to be passed to perform +/// detailed lookups in SymbolVendor and SymbolFile functions. struct CompilerContext { - CompilerContext(CompilerContextKind t, ConstString n) - : type(t), name(n) {} + CompilerContext(CompilerContextKind t, ConstString n) : kind(t), name(n) {} bool operator==(const CompilerContext &rhs) const { - return type == rhs.type && name == rhs.name; + return kind == rhs.kind && name == rhs.name; } + bool operator!=(const CompilerContext &rhs) const { return !(*this == rhs); } void Dump() const; - CompilerContextKind type; + CompilerContextKind kind; ConstString name; }; +/// Match \p context_chain against \p pattern, which may contain "Any" +/// kinds. The \p context_chain should *not* contain any "Any" kinds. +bool contextMatches(llvm::ArrayRef context_chain, + llvm::ArrayRef pattern); + class SymbolFileType : public std::enable_shared_from_this, public UserID { public: diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h index 8db841316901..53fa3361f340 100644 --- a/include/lldb/lldb-private-enumerations.h +++ b/include/lldb/lldb-private-enumerations.h @@ -251,18 +251,24 @@ enum class TypeValidatorResult : bool { Success = true, Failure = false }; //---------------------------------------------------------------------- // Enumerations that can be used to specify scopes types when looking up types. //---------------------------------------------------------------------- -enum class CompilerContextKind { +enum class CompilerContextKind : uint16_t { Invalid = 0, - TranslationUnit, - Module, - Namespace, - Class, - Structure, - Union, - Function, - Variable, - Enumeration, - Typedef + TranslationUnit = 1, + Module = 1 << 1, + Namespace = 1 << 2, + Class = 1 << 3, + Struct = 1 << 4, + Union = 1 << 5, + Function = 1 << 6, + Variable = 1 << 7, + Enum = 1 << 8, + Typedef = 1 << 9, + + Any = 1 << 15, + /// Match 0..n nested modules. + AnyModule = Any | Module, + /// Match any type. + AnyType = Any | Class | Struct | Union | Enum | Typedef }; //---------------------------------------------------------------------- diff --git a/lit/SymbolFile/DWARF/compilercontext.ll b/lit/SymbolFile/DWARF/compilercontext.ll new file mode 100644 index 000000000000..76637baec8c0 --- /dev/null +++ b/lit/SymbolFile/DWARF/compilercontext.ll @@ -0,0 +1,49 @@ +; Test finding types by CompilerContext. +; RUN: llc %s -filetype=obj -o %t.o +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,Module:SubModule,Struct:FromSubmoduleX" \ +; RUN: | FileCheck %s --check-prefix=NORESULTS +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,Module:SubModule,Struct:FromSubmodule" \ +; RUN: | FileCheck %s +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,AnyModule:*,Struct:FromSubmodule" \ +; RUN: | FileCheck %s +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="AnyModule:*,Struct:FromSubmodule" \ +; RUN: | FileCheck %s +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,Module:SubModule,AnyType:FromSubmodule" \ +; RUN: | FileCheck %s +; +; NORESULTS: Found 0 types +; CHECK: Found 1 types: +; CHECK: struct FromSubmodule { +; CHECK-NEXT: unsigned int x; +; CHECK-NEXT: unsigned int y; +; CHECK-NEXT: unsigned int z; +; CHECK-NEXT: } + +source_filename = "/t.c" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +!llvm.dbg.cu = !{!2} +!llvm.linker.options = !{} +!llvm.module.flags = !{!18, !19} +!llvm.ident = !{!22} + +; This simulates the debug info for a Clang module. +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, nameTableKind: GNU, retainedTypes: !{!11}) +!3 = !DIFile(filename: "t.c", directory: "/") +!8 = !DIModule(scope: !9, name: "SubModule", includePath: "", isysroot: "/") +!9 = !DIModule(scope: null, name: "CModule", includePath: "", isysroot: "/") +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "FromSubmodule", scope: !8, file: !3, line: 1, size: 96, elements: !13) +!13 = !{!14, !16, !17} +!14 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !3, line: 2, baseType: !15, size: 32) +!15 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!16 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !3, line: 2, baseType: !15, size: 32, offset: 32) +!17 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !11, file: !3, line: 2, baseType: !15, size: 32, offset: 64) +!18 = !{i32 2, !"Dwarf Version", i32 4} +!19 = !{i32 2, !"Debug Info Version", i32 3} +!22 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project 056f1b5cc7c2133f0cb3e30e7f24808d321096d7)"} diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index d98261101367..0fa9f92915e0 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -162,9 +162,8 @@ uint32_t SymbolFileBreakpad::FindTypes( return types.GetSize(); } -size_t -SymbolFileBreakpad::FindTypes(const std::vector &context, - bool append, TypeMap &types) { +size_t SymbolFileBreakpad::FindTypes(llvm::ArrayRef pattern, + bool append, TypeMap &types) { if (!append) types.Clear(); return types.GetSize(); diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 42996e9d66dd..965801b6af09 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -118,7 +118,7 @@ class SymbolFileBreakpad : public SymbolFile { llvm::DenseSet &searched_symbol_files, TypeMap &types) override; - size_t FindTypes(const std::vector &context, bool append, + size_t FindTypes(llvm::ArrayRef pattern, bool append, TypeMap &types) override; TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 6dde6078db5a..376ac8e712c2 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -145,7 +145,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { // If this type comes from a Clang module, look in the DWARF section // of the pcm file in the module cache. Clang generates DWO skeleton // units as breadcrumbs to find them. - std::vector decl_context; + llvm::SmallVector decl_context; die.GetDeclContext(decl_context); TypeMap dwo_types; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 36960dfe8f85..143a9f1ca10d 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -165,7 +165,8 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const { } } -void DWARFDIE::GetDeclContext(std::vector &context) const { +void DWARFDIE::GetDeclContext( + llvm::SmallVectorImpl &context) const { const dw_tag_t tag = Tag(); if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) return; @@ -174,40 +175,33 @@ void DWARFDIE::GetDeclContext(std::vector &context) const { parent.GetDeclContext(context); switch (tag) { case DW_TAG_module: - context.push_back( - CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + context.push_back({CompilerContextKind::Module, ConstString(GetName())}); break; case DW_TAG_namespace: - context.push_back(CompilerContext(CompilerContextKind::Namespace, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Namespace, ConstString(GetName())}); break; case DW_TAG_structure_type: - context.push_back(CompilerContext(CompilerContextKind::Structure, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Struct, ConstString(GetName())}); break; case DW_TAG_union_type: - context.push_back( - CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + context.push_back({CompilerContextKind::Union, ConstString(GetName())}); break; case DW_TAG_class_type: - context.push_back( - CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + context.push_back({CompilerContextKind::Class, ConstString(GetName())}); break; case DW_TAG_enumeration_type: - context.push_back(CompilerContext(CompilerContextKind::Enumeration, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Enum, ConstString(GetName())}); break; case DW_TAG_subprogram: - context.push_back(CompilerContext(CompilerContextKind::Function, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Function, ConstString(GetPubname())}); break; case DW_TAG_variable: - context.push_back(CompilerContext(CompilerContextKind::Variable, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Variable, ConstString(GetPubname())}); break; case DW_TAG_typedef: - context.push_back( - CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + context.push_back({CompilerContextKind::Typedef, ConstString(GetName())}); break; default: break; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index a4d99684eef0..f9a9524749e1 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -91,8 +91,8 @@ class DWARFDIE : public DWARFBaseDIE { /// Return this DIE's decl context as it is needed to look up types /// in Clang's -gmodules debug info format. - void - GetDeclContext(std::vector &context) const; + void GetDeclContext( + llvm::SmallVectorImpl &context) const; //---------------------------------------------------------------------- // Getting attribute values from the DIE. diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b905d7b342bf..6a10c4a830ea 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2505,15 +2505,15 @@ uint32_t SymbolFileDWARF::FindTypes( return num_die_matches; } -size_t SymbolFileDWARF::FindTypes(const std::vector &context, +size_t SymbolFileDWARF::FindTypes(llvm::ArrayRef pattern, bool append, TypeMap &types) { if (!append) types.Clear(); - if (context.empty()) + if (pattern.empty()) return 0; - ConstString name = context.back().name; + ConstString name = pattern.back().name; if (!name) return 0; @@ -2532,9 +2532,9 @@ size_t SymbolFileDWARF::FindTypes(const std::vector &context, if (die.GetCU()->GetLanguageType() == eLanguageTypeSwift) continue; - std::vector die_context; + llvm::SmallVector die_context; die.GetDeclContext(die_context); - if (die_context != context) + if (!contextMatches(die_context, pattern)) continue; Type *matching_type = ResolveType(die, true, true); diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 9dbbd116036e..fc4889451423 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -202,7 +202,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector &context, + size_t FindTypes(llvm::ArrayRef pattern, bool append, lldb_private::TypeMap &types) override; lldb_private::TypeList *GetTypeList() override; diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index d237a048cb5a..9adf40450cb0 100644 --- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1237,9 +1237,8 @@ uint32_t SymbolFileNativePDB::FindTypes( return match_count; } -size_t -SymbolFileNativePDB::FindTypes(const std::vector &context, - bool append, TypeMap &types) { +size_t SymbolFileNativePDB::FindTypes(llvm::ArrayRef pattern, + bool append, TypeMap &types) { return 0; } diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index ea1cc871748a..afd0a72f53cd 100644 --- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -144,7 +144,7 @@ class SymbolFileNativePDB : public SymbolFile { llvm::DenseSet &searched_symbol_files, TypeMap &types) override; - size_t FindTypes(const std::vector &context, bool append, + size_t FindTypes(llvm::ArrayRef pattern, bool append, TypeMap &types) override; TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override; diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index a4efade85614..e6dc132a6595 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1510,9 +1510,8 @@ void SymbolFilePDB::FindTypesByName( } } -size_t SymbolFilePDB::FindTypes( - const std::vector &contexts, bool append, - lldb_private::TypeMap &types) { +size_t SymbolFilePDB::FindTypes(llvm::ArrayRef pattern, + bool append, lldb_private::TypeMap &types) { return 0; } diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 72713aa0ba23..abc596ef3376 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -142,7 +142,7 @@ class SymbolFilePDB : public lldb_private::SymbolFile { llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector &context, + size_t FindTypes(llvm::ArrayRef pattern, bool append, lldb_private::TypeMap &types) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp index f73662578cfa..2cb1527a609b 100644 --- a/source/Symbol/SymbolFile.cpp +++ b/source/Symbol/SymbolFile.cpp @@ -197,7 +197,7 @@ uint32_t SymbolFile::FindTypes( return 0; } -size_t SymbolFile::FindTypes(const std::vector &context, +size_t SymbolFile::FindTypes(llvm::ArrayRef pattern, bool append, TypeMap &types) { if (!append) types.Clear(); diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp index 4c50c4108f36..b478d8284231 100644 --- a/source/Symbol/Type.cpp +++ b/source/Symbol/Type.cpp @@ -35,9 +35,38 @@ using namespace lldb; using namespace lldb_private; +bool lldb_private::contextMatches(llvm::ArrayRef context_chain, + llvm::ArrayRef pattern) { + auto ctx = context_chain.begin(); + auto ctx_end = context_chain.end(); + for (const CompilerContext &pat : pattern) { + // Early exit if the pattern is too long. + if (ctx == ctx_end) + return false; + if (*ctx != pat) { + // Skip any number of module matches. + if (pat.kind == CompilerContextKind::AnyModule) { + // Greedily match 0..n modules. + ctx = std::find_if(ctx, ctx_end, [](const CompilerContext &ctx) { + return ctx.kind != CompilerContextKind::Module; + }); + continue; + } + // See if there is a kind mismatch; they should have 1 bit in common. + if (((uint16_t)ctx->kind & (uint16_t)pat.kind) == 0) + return false; + // The name is ignored for AnyModule, but not for AnyType. + if (pat.kind != CompilerContextKind::AnyModule && ctx->name != pat.name) + return false; + } + ++ctx; + } + return true; +} + void CompilerContext::Dump() const { - switch (type) { - case CompilerContextKind::Invalid: + switch (kind) { + default: printf("Invalid"); break; case CompilerContextKind::TranslationUnit: @@ -52,7 +81,7 @@ void CompilerContext::Dump() const { case CompilerContextKind::Class: printf("Class"); break; - case CompilerContextKind::Structure: + case CompilerContextKind::Struct: printf("Structure"); break; case CompilerContextKind::Union: @@ -64,12 +93,18 @@ void CompilerContext::Dump() const { case CompilerContextKind::Variable: printf("Variable"); break; - case CompilerContextKind::Enumeration: + case CompilerContextKind::Enum: printf("Enumeration"); break; case CompilerContextKind::Typedef: printf("Typedef"); break; + case CompilerContextKind::AnyModule: + printf("AnyModule"); + break; + case CompilerContextKind::AnyType: + printf("AnyType"); + break; } printf("(\"%s\")\n", name.GetCString()); } diff --git a/tools/lldb-test/lldb-test.cpp b/tools/lldb-test/lldb-test.cpp index 3efb26b8c88c..32898d175919 100644 --- a/tools/lldb-test/lldb-test.cpp +++ b/tools/lldb-test/lldb-test.cpp @@ -138,6 +138,11 @@ static cl::opt cl::desc("Restrict search to the context of the given variable."), cl::value_desc("variable"), cl::sub(SymbolsSubcommand)); +static cl::opt CompilerContext( + "compiler-context", + cl::desc("Specify a compiler context as \"kind:name,...\"."), + cl::value_desc("context"), cl::sub(SymbolsSubcommand)); + static cl::list FunctionNameFlags( "function-flags", cl::desc("Function search flags:"), cl::values(clEnumValN(eFunctionNameTypeAuto, "auto", @@ -219,6 +224,46 @@ int evaluateMemoryMapCommands(Debugger &Dbg); } // namespace opts +std::vector parseCompilerContext() { + std::vector result; + if (opts::symbols::CompilerContext.empty()) + return result; + + StringRef str{opts::symbols::CompilerContext}; + SmallVector entries_str; + str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false); + for (auto entry_str : entries_str) { + StringRef key, value; + std::tie(key, value) = entry_str.split(':'); + auto kind = + StringSwitch(key) + .Case("TranslationUnit", CompilerContextKind::TranslationUnit) + .Case("Module", CompilerContextKind::Module) + .Case("Namespace", CompilerContextKind::Namespace) + .Case("Class", CompilerContextKind::Class) + .Case("Struct", CompilerContextKind::Struct) + .Case("Union", CompilerContextKind::Union) + .Case("Function", CompilerContextKind::Function) + .Case("Variable", CompilerContextKind::Variable) + .Case("Enum", CompilerContextKind::Enum) + .Case("Typedef", CompilerContextKind::Typedef) + .Case("AnyModule", CompilerContextKind::AnyModule) + .Case("AnyType", CompilerContextKind::AnyType) + .Default(CompilerContextKind::Invalid); + if (value.empty()) { + WithColor::error() << "compiler context entry has no \"name\"\n"; + exit(1); + } + result.push_back({kind, ConstString{value}}); + } + outs() << "Search context: {\n"; + for (auto entry: result) + entry.Dump(); + outs() << "}\n"; + + return result; +} + template static Error make_string_error(const char *Format, Args &&... args) { return llvm::make_error( @@ -460,8 +505,11 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) { DenseSet SearchedFiles; TypeMap Map; - Vendor.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX, - SearchedFiles, Map); + if (!Name.empty()) + Symfile.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX, + SearchedFiles, Map); + else + Symfile.FindTypes(parseCompilerContext(), true, Map); outs() << formatv("Found {0} types:\n", Map.GetSize()); StreamString Stream; diff --git a/unittests/Symbol/TestType.cpp b/unittests/Symbol/TestType.cpp index 4b9b7bfaba33..d23d7a53e03e 100644 --- a/unittests/Symbol/TestType.cpp +++ b/unittests/Symbol/TestType.cpp @@ -48,3 +48,47 @@ TEST(Type, GetTypeScopeAndBasename) { "std::set>::iterator", true, "std::set>::", "iterator"); } + +TEST(Type, CompilerContextPattern) { + std::vector mms = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Struct, ConstString("S")}}; + EXPECT_TRUE(contextMatches(mms, mms)); + std::vector mmc = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Class, ConstString("S")}}; + EXPECT_FALSE(contextMatches(mms, mmc)); + std::vector ms = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Struct, ConstString("S")}}; + std::vector mas = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::AnyModule, ConstString("*")}, + {CompilerContextKind::Struct, ConstString("S")}}; + EXPECT_TRUE(contextMatches(mms, mas)); + EXPECT_TRUE(contextMatches(ms, mas)); + EXPECT_FALSE(contextMatches(mas, ms)); + std::vector mmms = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Module, ConstString("C")}, + {CompilerContextKind::Struct, ConstString("S")}}; + EXPECT_TRUE(contextMatches(mmms, mas)); + std::vector mme = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Enum, ConstString("S")}}; + std::vector mma = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::AnyType, ConstString("S")}}; + EXPECT_TRUE(contextMatches(mme, mma)); + EXPECT_TRUE(contextMatches(mms, mma)); + std::vector mme2 = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Enum, ConstString("S2")}}; + EXPECT_FALSE(contextMatches(mme2, mma)); +} From 6e34dafb623542a2f3dfb39006e82be8ec61337c Mon Sep 17 00:00:00 2001 From: Gwen Mittertreiner Date: Wed, 21 Aug 2019 12:02:29 -0700 Subject: [PATCH 4/6] Update for upstream rL369555 - CompilerContextKind::Enumeration -> CompilerContextKind::Enum - CompilerContextKind::Structure -> CompilerContextKind::Struct - CompilerContext::type -> CompilerContext::kind - GetDeclContext now takes a llvm::SmallVectorImpl (cherry picked from commit f721d2481e9cef777e682975ee028df1bab5cf94) --- .../Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp | 10 +++++----- source/Symbol/SwiftASTContext.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp index 988385a3eb8f..e47d0d7e3348 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp @@ -228,7 +228,7 @@ lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc, void DWARFASTParserSwift::GetClangType(const DWARFDIE &die, llvm::StringRef mangled_name, TypeMap &clang_types) const { - std::vector decl_context; + llvm::SmallVector decl_context; die.GetDeclContext(decl_context); if (!decl_context.size()) return; @@ -254,7 +254,7 @@ void DWARFASTParserSwift::GetClangType(const DWARFDIE &die, return; for (NodePointer child : *node) if (child->getKind() == Node::Kind::Identifier && child->hasText()) { - decl_context.back().type = CompilerContextKind::Typedef; + decl_context.back().kind = CompilerContextKind::Typedef; decl_context.back().name = ConstString(child->getText()); return; } @@ -264,13 +264,13 @@ void DWARFASTParserSwift::GetClangType(const DWARFDIE &die, auto *sym_file = die.GetCU()->GetSymbolFileDWARF(); sym_file->UpdateExternalModuleListIfNeeded(); - CompilerContextKind kinds[] = {decl_context.back().type, + CompilerContextKind kinds[] = {decl_context.back().kind, CompilerContextKind::Union, - CompilerContextKind::Enumeration}; + CompilerContextKind::Enum}; // The Swift projection of all Clang type is a struct; search every kind. for (CompilerContextKind kind : kinds) { - decl_context.back().type = kind; + decl_context.back().kind = kind; // Search any modules referenced by DWARF. for (const auto &name_module : sym_file->getExternalTypeModules()) { if (!name_module.second) diff --git a/source/Symbol/SwiftASTContext.cpp b/source/Symbol/SwiftASTContext.cpp index ab10b184d756..9e90ced19b26 100644 --- a/source/Symbol/SwiftASTContext.cpp +++ b/source/Symbol/SwiftASTContext.cpp @@ -3198,7 +3198,7 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { llvm::SmallVectorImpl &results) override { std::vector decl_context; ConstString name_cs(name); - decl_context.push_back({CompilerContextKind::Structure, name_cs}); + decl_context.push_back({CompilerContextKind::Struct, name_cs}); auto clang_importer = m_swift_ast_ctx.GetClangImporter(); if (!clang_importer) return; From 187cca7b1f3488fd8e41271bc9092ce2aeadea14 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 21 Aug 2019 17:26:56 -0700 Subject: [PATCH 5/6] DWARFImporterDelegate: Adopt the new FindFiles API. By using the new LLDB FindFiles API that llows for fuzzy CompilerContext matching, we can unify the two lookup implementations, dramatically improve the performance by only looking types up once, and look for types inside of unknown submodules. rdar://problem/49233932 --- include/lldb/Symbol/SymbolVendor.h | 2 +- .../C/TestSwiftDWARFImporterC.py | 3 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 2 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 2 +- .../DWARF/SymbolFileDWARFDebugMap.h | 2 +- source/Symbol/SwiftASTContext.cpp | 85 +++++++++---------- source/Symbol/SymbolVendor.cpp | 2 +- 7 files changed, 48 insertions(+), 50 deletions(-) diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h index 8485ea0b740e..7cc022e9d3f0 100644 --- a/include/lldb/Symbol/SymbolVendor.h +++ b/include/lldb/Symbol/SymbolVendor.h @@ -105,7 +105,7 @@ class SymbolVendor : public ModuleChild, public PluginInterface { llvm::DenseSet &searched_symbol_files, TypeMap &types); - virtual size_t FindTypes(const std::vector &context, + virtual size_t FindTypes(llvm::ArrayRef context, bool append, TypeMap &types); virtual CompilerDeclContext diff --git a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py index 6c06a644621f..459d1c594188 100644 --- a/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py +++ b/packages/Python/lldbsuite/test/lang/swift/dwarfimporter/C/TestSwiftDWARFImporterC.py @@ -57,8 +57,7 @@ def test_dwarf_importer(self): self.expect("ta v pureSwiftStruct", substrs=["pure swift"]) self.expect("ta v swiftStructCMember", substrs=["point", "x = 3", "y = 4", - # FIXME: - # "sub", "x = 1", "y = 2", "z = 3", + "sub", "x = 1", "y = 2", "z = 3", "swift struct c member"]) self.expect("ta v typedef", substrs=["x = 5", "y = 6"]) self.expect("ta v union", substrs=["(DoubleLongUnion)", "long_val = 42"]) diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 6a10c4a830ea..2e94e005bdc4 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2558,7 +2558,7 @@ size_t SymbolFileDWARF::FindTypes(llvm::ArrayRef pattern, if (ModuleSP external_module_sp = pair.second) { SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); if (sym_vendor) - num_matches += sym_vendor->FindTypes(context, true, types); + num_matches += sym_vendor->FindTypes(pattern, true, types); } return num_matches; } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 1c47197ef410..2c65c24a9f2a 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1198,7 +1198,7 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes( } size_t -SymbolFileDWARFDebugMap::FindTypes(const std::vector &context, +SymbolFileDWARFDebugMap::FindTypes(llvm::ArrayRef context, bool append, TypeMap &types) { if (!append) types.Clear(); diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index b0120eba7cc6..9adc415f8d57 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -121,7 +121,7 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile { bool append, uint32_t max_matches, llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector &context, + size_t FindTypes(llvm::ArrayRef context, bool append, lldb_private::TypeMap &types) override; lldb_private::CompilerDeclContext FindNamespace( lldb_private::ConstString name, diff --git a/source/Symbol/SwiftASTContext.cpp b/source/Symbol/SwiftASTContext.cpp index 9e90ced19b26..d291bf7486c4 100644 --- a/source/Symbol/SwiftASTContext.cpp +++ b/source/Symbol/SwiftASTContext.cpp @@ -3188,6 +3188,32 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { } return nullptr; } + + static CompilerContextKind + GetCompilerContextKind(llvm::Optional kind) { + if (!kind) + return CompilerContextKind::AnyType; + switch (*kind) { + case swift::ClangTypeKind::Typedef: + /*=swift::ClangTypeKind::ObjCClass:*/ + return (CompilerContextKind)((uint16_t)CompilerContextKind::Any | + (uint16_t)CompilerContextKind::Typedef | + (uint16_t)CompilerContextKind::Struct); + break; + case swift::ClangTypeKind::Tag: + return (CompilerContextKind)((uint16_t)CompilerContextKind::Any | + (uint16_t)CompilerContextKind::Class | + (uint16_t)CompilerContextKind::Struct | + (uint16_t)CompilerContextKind::Union | + (uint16_t)CompilerContextKind::Enum); + // case swift::ClangTypeKind::ObjCProtocol: + // Not implemented since Objective-C protocols aren't yet + // described in DWARF. + default: + return CompilerContextKind::Invalid; + } + } + public: SwiftDWARFImporterDelegate(SwiftASTContext &swift_ast_ctx) @@ -3196,9 +3222,6 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { void lookupValue(StringRef name, llvm::Optional kind, StringRef inModule, llvm::SmallVectorImpl &results) override { - std::vector decl_context; - ConstString name_cs(name); - decl_context.push_back({CompilerContextKind::Struct, name_cs}); auto clang_importer = m_swift_ast_ctx.GetClangImporter(); if (!clang_importer) return; @@ -3207,52 +3230,27 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { return; // Find the type in the debug info. - TypeList clang_types; + TypeMap clang_types; + llvm::SmallVector decl_context; // Perform a lookup in a specific module, if requested. - if (!inModule.empty()) { - TypeMap type_map; - std::vector decl_context; - ConstString mod_name(inModule); - ConstString type_name(name); - // There's a bit of an impedance mismatch between the - // interfaces, Swift passes in either inModule (when looking up - // an inner Clang type) or kind (when coming through - // ASTDemangler), but it would be much more efficient if we had - // both. Alternatively, adding a wildcard CompilerContextKind - // would also save us from doing reedundant lookups here. - CompilerContextKind cc_kinds[] = { - CompilerContextKind::Class, CompilerContextKind::Structure, - CompilerContextKind::Union, CompilerContextKind::Enumeration, - CompilerContextKind::Typedef}; - for (auto cc_kind : cc_kinds) - if (module->GetSymbolVendor()->FindTypes( - {{CompilerContextKind::Module, mod_name}, {cc_kind, type_name}}, - true, type_map)) - break; - type_map.ForEach([&](lldb::TypeSP &type_sp) { - clang_types.Insert(type_sp); - return true; - }); - } else { - // Search globally. - const bool exact_match = true; - const uint32_t max_matches = UINT32_MAX; - llvm::DenseSet searched_symbol_files; - module->FindTypes(name_cs, exact_match, max_matches, - searched_symbol_files, clang_types); - } + if (!inModule.empty()) + decl_context.push_back( + {CompilerContextKind::Module, ConstString(inModule)}); + // Swift doesn't keep track of submodules. + decl_context.push_back({CompilerContextKind::AnyModule, ConstString()}); + decl_context.push_back({GetCompilerContextKind(kind), ConstString(name)}); + module->GetSymbolVendor()->FindTypes(decl_context, true, clang_types); clang::FileSystemOptions file_system_options; clang::FileManager file_manager(file_system_options); - for (unsigned i = 0; i < clang_types.GetSize(); ++i) { - TypeSP clang_type_sp = clang_types.GetTypeAtIndex(i); + clang_types.ForEach([&](lldb::TypeSP &clang_type_sp) { if (!clang_type_sp) - continue; + return true; // Filter out types with a mismatching type kind. if (kind && HasTypeKind(clang_type_sp, *kind)) - continue; + return true; // Realize the full type. CompilerType compiler_type = clang_type_sp->GetFullCompilerType(); @@ -3261,13 +3259,13 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { auto *type_system = llvm::dyn_cast_or_null( compiler_type.GetTypeSystem()); if (!type_system) - continue; + return true; // Import the type into the DWARFImporter's context. clang::ASTContext &to_ctx = clang_importer->getClangASTContext(); clang::ASTContext *from_ctx = type_system->getASTContext(); if (!from_ctx) - continue; + return true; clang::ASTImporter importer(to_ctx, file_manager, *from_ctx, file_manager, false); clang::QualType clang_type( @@ -3285,7 +3283,8 @@ class SwiftDWARFImporterDelegate : public swift::DWARFImporterDelegate { if (clang::Decl *clang_decl = GetDeclForTypeAndKind(clang_type, kind)) results.push_back(clang_decl); } - } + return true; + }); } }; } // namespace lldb_private diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp index 57aaed51d279..890cb2f258a1 100644 --- a/source/Symbol/SymbolVendor.cpp +++ b/source/Symbol/SymbolVendor.cpp @@ -335,7 +335,7 @@ size_t SymbolVendor::FindTypes( return 0; } -size_t SymbolVendor::FindTypes(const std::vector &context, +size_t SymbolVendor::FindTypes(llvm::ArrayRef context, bool append, TypeMap &types) { ModuleSP module_sp(GetModule()); if (module_sp) { From 47d71a2854ad20d1a335b0f97f7bd465d54b4bfb Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 21 Aug 2019 17:42:31 -0700 Subject: [PATCH 6/6] Make lldb-test compile on stable. --- tools/lldb-test/lldb-test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lldb-test/lldb-test.cpp b/tools/lldb-test/lldb-test.cpp index 32898d175919..cf504aa987c7 100644 --- a/tools/lldb-test/lldb-test.cpp +++ b/tools/lldb-test/lldb-test.cpp @@ -497,6 +497,7 @@ Error opts::symbols::findNamespaces(lldb_private::Module &Module) { Error opts::symbols::findTypes(lldb_private::Module &Module) { SymbolVendor &Vendor = *Module.GetSymbolVendor(); + auto &Symfile = Vendor; Expected ContextOr = getDeclContext(Vendor); if (!ContextOr) return ContextOr.takeError();