summaryrefslogtreecommitdiff
path: root/lldb/source/Symbol/CompileUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol/CompileUnit.cpp')
-rw-r--r--lldb/source/Symbol/CompileUnit.cpp231
1 files changed, 115 insertions, 116 deletions
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 41086d2df3df..b05036e27fcf 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -12,6 +12,7 @@
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Language.h"
+#include "lldb/Utility/Timer.h"
using namespace lldb;
using namespace lldb_private;
@@ -20,30 +21,21 @@ CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
const char *pathname, const lldb::user_id_t cu_sym_id,
lldb::LanguageType language,
lldb_private::LazyBool is_optimized)
- : ModuleChild(module_sp), FileSpec(pathname), UserID(cu_sym_id),
- m_user_data(user_data), m_language(language), m_flags(0),
- m_support_files(), m_line_table_up(), m_variables(),
- m_is_optimized(is_optimized) {
- if (language != eLanguageTypeUnknown)
- m_flags.Set(flagsParsedLanguage);
- assert(module_sp);
-}
+ : CompileUnit(module_sp, user_data, FileSpec(pathname), cu_sym_id, language,
+ is_optimized) {}
CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
const FileSpec &fspec, const lldb::user_id_t cu_sym_id,
lldb::LanguageType language,
lldb_private::LazyBool is_optimized)
- : ModuleChild(module_sp), FileSpec(fspec), UserID(cu_sym_id),
- m_user_data(user_data), m_language(language), m_flags(0),
- m_support_files(), m_line_table_up(), m_variables(),
+ : ModuleChild(module_sp), UserID(cu_sym_id), m_user_data(user_data),
+ m_language(language), m_flags(0), m_file_spec(fspec),
m_is_optimized(is_optimized) {
if (language != eLanguageTypeUnknown)
m_flags.Set(flagsParsedLanguage);
assert(module_sp);
}
-CompileUnit::~CompileUnit() {}
-
void CompileUnit::CalculateSymbolContext(SymbolContext *sc) {
sc->comp_unit = this;
GetModule()->CalculateSymbolContext(sc);
@@ -62,7 +54,7 @@ void CompileUnit::GetDescription(Stream *s,
lldb::DescriptionLevel level) const {
const char *language = Language::GetNameForLanguageType(m_language);
*s << "id = " << (const UserID &)*this << ", file = \""
- << (const FileSpec &)*this << "\", language = \"" << language << '"';
+ << this->GetPrimaryFile() << "\", language = \"" << language << '"';
}
void CompileUnit::ForeachFunction(
@@ -81,6 +73,31 @@ void CompileUnit::ForeachFunction(
return;
}
+lldb::FunctionSP CompileUnit::FindFunction(
+ llvm::function_ref<bool(const FunctionSP &)> matching_lambda) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "CompileUnit::FindFunction");
+
+ lldb::ModuleSP module = CalculateSymbolContextModule();
+
+ if (!module)
+ return {};
+
+ SymbolFile *symbol_file = module->GetSymbolFile();
+
+ if (!symbol_file)
+ return {};
+
+ // m_functions_by_uid is filled in lazily but we need all the entries.
+ symbol_file->ParseFunctions(*this);
+
+ for (auto &p : m_functions_by_uid) {
+ if (matching_lambda(p.second))
+ return p.second;
+ }
+ return {};
+}
+
// Dump the current contents of this object. No functions that cause on demand
// parsing of functions, globals, statics are called, so this is a good
// function to call to get an idea of the current contents of the CompileUnit
@@ -91,8 +108,7 @@ void CompileUnit::Dump(Stream *s, bool show_context) const {
s->Printf("%p: ", static_cast<const void *>(this));
s->Indent();
*s << "CompileUnit" << static_cast<const UserID &>(*this) << ", language = \""
- << language << "\", file = '" << static_cast<const FileSpec &>(*this)
- << "'\n";
+ << language << "\", file = '" << GetPrimaryFile() << "'\n";
// m_types.Dump(s);
@@ -191,53 +207,50 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) {
return m_variables;
}
+std::vector<uint32_t> FindFileIndexes(const FileSpecList &files, const FileSpec &file) {
+ std::vector<uint32_t> result;
+ uint32_t idx = -1;
+ while ((idx = files.FindFileIndex(idx + 1, file, /*full=*/true)) !=
+ UINT32_MAX)
+ result.push_back(idx);
+ return result;
+}
+
uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,
const FileSpec *file_spec_ptr, bool exact,
LineEntry *line_entry_ptr) {
- uint32_t file_idx = 0;
+ if (!file_spec_ptr)
+ file_spec_ptr = &GetPrimaryFile();
+ std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(), *file_spec_ptr);
+ if (file_indexes.empty())
+ return UINT32_MAX;
- if (file_spec_ptr) {
- file_idx = GetSupportFiles().FindFileIndex(1, *file_spec_ptr, true);
- if (file_idx == UINT32_MAX)
- return UINT32_MAX;
- } else {
- // All the line table entries actually point to the version of the Compile
- // Unit that is in the support files (the one at 0 was artificially added.)
- // So prefer the one further on in the support files if it exists...
- const FileSpecList &support_files = GetSupportFiles();
- const bool full = true;
- file_idx = support_files.FindFileIndex(
- 1, support_files.GetFileSpecAtIndex(0), full);
- if (file_idx == UINT32_MAX)
- file_idx = 0;
- }
LineTable *line_table = GetLineTable();
if (line_table)
- return line_table->FindLineEntryIndexByFileIndex(start_idx, file_idx, line,
- exact, line_entry_ptr);
+ return line_table->FindLineEntryIndexByFileIndex(
+ start_idx, file_indexes, line, exact, line_entry_ptr);
return UINT32_MAX;
}
-uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
- uint32_t line, bool check_inlines,
- bool exact,
- SymbolContextItem resolve_scope,
- SymbolContextList &sc_list) {
+void CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
+ uint32_t line, bool check_inlines,
+ bool exact,
+ SymbolContextItem resolve_scope,
+ SymbolContextList &sc_list) {
// First find all of the file indexes that match our "file_spec". If
// "file_spec" has an empty directory, then only compare the basenames when
// finding file indexes
std::vector<uint32_t> file_indexes;
- const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec =
- FileSpec::Equal(file_spec, *this, full_match);
+ FileSpec::Match(file_spec, this->GetPrimaryFile());
// If we are not looking for inlined functions and our file spec doesn't
// match then we are done...
if (!file_spec_matches_cu_file_spec && !check_inlines)
- return 0;
+ return;
uint32_t file_idx =
- GetSupportFiles().FindFileIndex(1, file_spec, true);
+ GetSupportFiles().FindFileIndex(0, file_spec, true);
while (file_idx != UINT32_MAX) {
file_indexes.push_back(file_idx);
file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true);
@@ -245,84 +258,67 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
const size_t num_file_indexes = file_indexes.size();
if (num_file_indexes == 0)
- return 0;
-
- const uint32_t prev_size = sc_list.GetSize();
+ return;
SymbolContext sc(GetModule());
sc.comp_unit = this;
- if (line != 0) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table != nullptr) {
- uint32_t found_line;
- uint32_t line_idx;
-
- if (num_file_indexes == 1) {
- // We only have a single support file that matches, so use the line
- // table function that searches for a line entries that match a single
- // support file index
- LineEntry line_entry;
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- 0, file_indexes.front(), line, exact, &line_entry);
-
- // If "exact == true", then "found_line" will be the same as "line". If
- // "exact == false", the "found_line" will be the closest line entry
- // with a line number greater than "line" and we will use this for our
- // subsequent line exact matches below.
- found_line = line_entry.line;
-
- while (line_idx != UINT32_MAX) {
- // If they only asked for the line entry, then we're done, we can
- // just copy that over. But if they wanted more than just the line
- // number, fill it in.
- if (resolve_scope == eSymbolContextLineEntry) {
- sc.line_entry = line_entry;
- } else {
- line_entry.range.GetBaseAddress().CalculateSymbolContext(
- &sc, resolve_scope);
- }
-
- sc_list.Append(sc);
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_indexes.front(), found_line, true,
- &line_entry);
- }
- } else {
- // We found multiple support files that match "file_spec" so use the
- // line table function that searches for a line entries that match a
- // multiple support file indexes.
- LineEntry line_entry;
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- 0, file_indexes, line, exact, &line_entry);
-
- // If "exact == true", then "found_line" will be the same as "line". If
- // "exact == false", the "found_line" will be the closest line entry
- // with a line number greater than "line" and we will use this for our
- // subsequent line exact matches below.
- found_line = line_entry.line;
-
- while (line_idx != UINT32_MAX) {
- if (resolve_scope == eSymbolContextLineEntry) {
- sc.line_entry = line_entry;
- } else {
- line_entry.range.GetBaseAddress().CalculateSymbolContext(
- &sc, resolve_scope);
- }
-
- sc_list.Append(sc);
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_indexes, found_line, true, &line_entry);
- }
- }
+ if (line == 0) {
+ if (file_spec_matches_cu_file_spec && !check_inlines) {
+ // only append the context if we aren't looking for inline call sites by
+ // file and line and if the file spec matches that of the compile unit
+ sc_list.Append(sc);
}
- } else if (file_spec_matches_cu_file_spec && !check_inlines) {
- // only append the context if we aren't looking for inline call sites by
- // file and line and if the file spec matches that of the compile unit
+ return;
+ }
+
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table == nullptr)
+ return;
+
+ uint32_t line_idx;
+ LineEntry line_entry;
+
+ if (num_file_indexes == 1) {
+ // We only have a single support file that matches, so use the line
+ // table function that searches for a line entries that match a single
+ // support file index
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ 0, file_indexes.front(), line, exact, &line_entry);
+ } else {
+ // We found multiple support files that match "file_spec" so use the
+ // line table function that searches for a line entries that match a
+ // multiple support file indexes.
+ line_idx = line_table->FindLineEntryIndexByFileIndex(0, file_indexes, line,
+ exact, &line_entry);
+ }
+
+ // If "exact == true", then "found_line" will be the same as "line". If
+ // "exact == false", the "found_line" will be the closest line entry
+ // with a line number greater than "line" and we will use this for our
+ // subsequent line exact matches below.
+ uint32_t found_line = line_entry.line;
+
+ while (line_idx != UINT32_MAX) {
+ // If they only asked for the line entry, then we're done, we can
+ // just copy that over. But if they wanted more than just the line
+ // number, fill it in.
+ if (resolve_scope == eSymbolContextLineEntry) {
+ sc.line_entry = line_entry;
+ } else {
+ line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc,
+ resolve_scope);
+ }
+
sc_list.Append(sc);
+ if (num_file_indexes == 1)
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ line_idx + 1, file_indexes.front(), found_line, true, &line_entry);
+ else
+ line_idx = line_table->FindLineEntryIndexByFileIndex(
+ line_idx + 1, file_indexes, found_line, true, &line_entry);
}
- return sc_list.GetSize() - prev_size;
}
bool CompileUnit::GetIsOptimized() {
@@ -353,9 +349,12 @@ const std::vector<SourceModule> &CompileUnit::GetImportedModules() {
return m_imported_modules;
}
-void CompileUnit::ForEachExternalModule(llvm::function_ref<void(ModuleSP)> f) {
+bool CompileUnit::ForEachExternalModule(
+ llvm::DenseSet<SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
if (SymbolFile *symfile = GetModule()->GetSymbolFile())
- symfile->ForEachExternalModule(*this, f);
+ return symfile->ForEachExternalModule(*this, visited_symbol_files, lambda);
+ return false;
}
const FileSpecList &CompileUnit::GetSupportFiles() {