diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -152,14 +152,84 @@ /// /// \see CompileUnit::GetSupportFiles() /// \see FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const + template uint32_t - FindLineEntryIndexByFileIndex(uint32_t start_idx, uint32_t file_idx, + FindLineEntryIndexByFileIndex(uint32_t start_idx, T file_idx, const SourceLocationSpec &src_location_spec, - LineEntry *line_entry_ptr); + LineEntry *line_entry_ptr) { + const size_t count = m_entries.size(); + size_t best_match = UINT32_MAX; + + if (!line_entry_ptr) + return best_match; + + const uint32_t line = src_location_spec.GetLine(); + const auto column = src_location_spec.GetColumn(); + const bool exact = src_location_spec.GetExactMatch(); + + std::function file_idx_matcher; + if constexpr (std::is_integral()) { + file_idx_matcher = [this, file_idx](int idx) { + return m_entries[idx].file_idx == file_idx; + }; + } else { + file_idx_matcher = [this, file_idx](int idx) { + return llvm::is_contained(file_idx, m_entries[idx].file_idx); + }; + } + + for (size_t idx = start_idx; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; + + if (!file_idx_matcher(idx)) + continue; + + // Exact match always wins. Otherwise try to find the closest line > the + // desired line. + // FIXME: Maybe want to find the line closest before and the line closest + // after and + // if they're not in the same function, don't return a match. + + if (!column) { + if (m_entries[idx].line < line) { + continue; + } else if (m_entries[idx].line == line) { + ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); + return idx; + } else if (!exact) { + if (best_match == UINT32_MAX || + m_entries[idx].line < m_entries[best_match].line) + best_match = idx; + } + } else { + if (m_entries[idx].line < line) { + continue; + } else if (m_entries[idx].line == line && + m_entries[idx].column == *column) { + ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); + return idx; + } else if (!exact) { + if (best_match == UINT32_MAX) + best_match = idx; + else if (m_entries[idx].line == m_entries[best_match].line) { + if (std::abs(m_entries[idx].column - *column) < + std::abs(m_entries[best_match].column - *column)) + best_match = idx; + } + } + } + } - uint32_t FindLineEntryIndexByFileIndex( - uint32_t start_idx, const std::vector &file_indexes, - const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr); + if (best_match != UINT32_MAX) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); + return best_match; + } + return UINT32_MAX; + } size_t FineLineEntriesForFileIndex(uint32_t file_idx, bool append, SymbolContextList &sc_list); diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -13,6 +13,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Utility/Stream.h" #include +#include using namespace lldb; using namespace lldb_private; @@ -302,97 +303,6 @@ return true; } -uint32_t LineTable::FindLineEntryIndexByFileIndex( - uint32_t start_idx, const std::vector &file_indexes, - const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) { - - const size_t count = m_entries.size(); - size_t best_match = UINT32_MAX; - - for (size_t idx = start_idx; idx < count; ++idx) { - // Skip line table rows that terminate the previous row (is_terminal_entry - // is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (!llvm::is_contained(file_indexes, m_entries[idx].file_idx)) - continue; - - // Exact match always wins. Otherwise try to find the closest line > the - // desired line. - // FIXME: Maybe want to find the line closest before and the line closest - // after and - // if they're not in the same function, don't return a match. - - uint32_t line = src_location_spec.GetLine(); - - if (m_entries[idx].line < line) { - continue; - } else if (m_entries[idx].line == line) { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); - return idx; - } else if (!src_location_spec.GetExactMatch()) { - if (best_match == UINT32_MAX) - best_match = idx; - else if (m_entries[idx].line < m_entries[best_match].line) - best_match = idx; - } - } - - if (best_match != UINT32_MAX) { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); - return best_match; - } - return UINT32_MAX; -} - -uint32_t LineTable::FindLineEntryIndexByFileIndex( - uint32_t start_idx, uint32_t file_idx, - const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) { - const size_t count = m_entries.size(); - size_t best_match = UINT32_MAX; - - for (size_t idx = start_idx; idx < count; ++idx) { - // Skip line table rows that terminate the previous row (is_terminal_entry - // is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (m_entries[idx].file_idx != file_idx) - continue; - - // Exact match always wins. Otherwise try to find the closest line > the - // desired line. - // FIXME: Maybe want to find the line closest before and the line closest - // after and - // if they're not in the same function, don't return a match. - - uint32_t line = src_location_spec.GetLine(); - - if (m_entries[idx].line < line) { - continue; - } else if (m_entries[idx].line == line) { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); - return idx; - } else if (!src_location_spec.GetExactMatch()) { - if (best_match == UINT32_MAX) - best_match = idx; - else if (m_entries[idx].line < m_entries[best_match].line) - best_match = idx; - } - } - - if (best_match != UINT32_MAX) { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); - return best_match; - } - return UINT32_MAX; -} - size_t LineTable::FineLineEntriesForFileIndex(uint32_t file_idx, bool append, SymbolContextList &sc_list) {