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
llvm-svn: 369555
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index 73ee7073..d5f5145 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -318,9 +318,8 @@
return types.GetSize();
}
-size_t
-SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context,
- bool append, TypeMap &types) {
+size_t SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
+ bool append, TypeMap &types) {
if (!append)
types.Clear();
return types.GetSize();
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index 6f25627..def975e 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -116,7 +116,7 @@
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
- size_t FindTypes(const std::vector<CompilerContext> &context, bool append,
+ size_t FindTypes(llvm::ArrayRef<CompilerContext> pattern, bool append,
TypeMap &types) override;
llvm::Expected<TypeSystem &>
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 8a4e40d..f0c4637 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -144,11 +144,11 @@
// 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<CompilerContext> decl_context;
+ llvm::SmallVector<CompilerContext, 4> decl_context;
die.GetDeclContext(decl_context);
TypeMap dwo_types;
- if (!dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, true,
+ if (!dwo_module_sp->GetSymbolFile()->FindTypes({decl_context}, true,
dwo_types)) {
if (!IsClangModuleFwdDecl(die))
return TypeSP();
@@ -159,7 +159,7 @@
for (const auto &name_module : sym_file.getExternalTypeModules()) {
if (!name_module.second)
continue;
- if (name_module.second->GetSymbolFile()->FindTypes(decl_context, true,
+ if (name_module.second->GetSymbolFile()->FindTypes({decl_context}, true,
dwo_types))
break;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 9d97ca1..5ee0687 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -342,7 +342,8 @@
}
}
-void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const {
+void DWARFDIE::GetDeclContext(
+ llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const {
const dw_tag_t tag = Tag();
if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
return;
@@ -351,40 +352,33 @@
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/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 7753ec9..a779c58 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -78,8 +78,8 @@
/// 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<lldb_private::CompilerContext> &context) const;
+ void GetDeclContext(
+ llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const;
// Getting attribute values from the DIE.
//
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 17f9241..ba63b41 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2484,16 +2484,16 @@
return num_die_matches;
}
-size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
+size_t SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
bool append, TypeMap &types) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
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;
@@ -2508,9 +2508,9 @@
DWARFDIE die = GetDIE(die_ref);
if (die) {
- std::vector<CompilerContext> die_context;
+ llvm::SmallVector<CompilerContext, 4> 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/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 25e231e..0d59013 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -184,7 +184,7 @@
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
- size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context,
+ size_t FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
bool append, lldb_private::TypeMap &types) override;
size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 20c8733..32b13c9 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1269,9 +1269,8 @@
return match_count;
}
-size_t
-SymbolFileNativePDB::FindTypes(const std::vector<CompilerContext> &context,
- bool append, TypeMap &types) {
+size_t SymbolFileNativePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
+ bool append, TypeMap &types) {
return 0;
}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 6ddbea7..f64fb4f 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -134,7 +134,7 @@
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
- size_t FindTypes(const std::vector<CompilerContext> &context, bool append,
+ size_t FindTypes(llvm::ArrayRef<CompilerContext> pattern, bool append,
TypeMap &types) override;
llvm::Expected<TypeSystem &>
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 59c0b5c..51b84c4 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1584,9 +1584,8 @@
}
}
-size_t SymbolFilePDB::FindTypes(
- const std::vector<lldb_private::CompilerContext> &contexts, bool append,
- lldb_private::TypeMap &types) {
+size_t SymbolFilePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
+ bool append, lldb_private::TypeMap &types) {
return 0;
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 8e4d40a..15eed0f 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -132,7 +132,7 @@
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
- size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context,
+ size_t FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
bool append, lldb_private::TypeMap &types) override;
void FindTypesByRegex(const lldb_private::RegularExpression ®ex,
diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp
index 8b9d8d3..1cbfb4c 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -149,7 +149,7 @@
return 0;
}
-size_t SymbolFile::FindTypes(const std::vector<CompilerContext> &context,
+size_t SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
bool append, TypeMap &types) {
if (!append)
types.Clear();
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 717b49d..5666590 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -33,9 +33,38 @@
using namespace lldb;
using namespace lldb_private;
+bool lldb_private::contextMatches(llvm::ArrayRef<CompilerContext> context_chain,
+ llvm::ArrayRef<CompilerContext> 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:
@@ -50,7 +79,7 @@
case CompilerContextKind::Class:
printf("Class");
break;
- case CompilerContextKind::Structure:
+ case CompilerContextKind::Struct:
printf("Structure");
break;
case CompilerContextKind::Union:
@@ -62,12 +91,18 @@
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());
}