Skip to content

[lldb] Allow languages to filter breakpoints set by line #83908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 14, 2024

Conversation

felipepiovezan
Copy link
Contributor

Some languages may create artificial functions that have no real user code, even though there is line table information for them. One such case is with coroutine code that receives the CoroSplitter transformation in LLVM IR. That code transformation creates many different Functions, cloning one Instruction into many Instructions in many different Functions and copying the associated debug locations.

It would be difficult to make that pass delete debug locations of cloned instructions in a language agnostic way (is it even possible?), but LLDB can ignore certain locations by querying its Language APIs and having it decide based on, for example, mangling information.

@llvmbot
Copy link
Member

llvmbot commented Mar 4, 2024

@llvm/pr-subscribers-lldb

Author: Felipe de Azevedo Piovezan (felipepiovezan)

Changes

Some languages may create artificial functions that have no real user code, even though there is line table information for them. One such case is with coroutine code that receives the CoroSplitter transformation in LLVM IR. That code transformation creates many different Functions, cloning one Instruction into many Instructions in many different Functions and copying the associated debug locations.

It would be difficult to make that pass delete debug locations of cloned instructions in a language agnostic way (is it even possible?), but LLDB can ignore certain locations by querying its Language APIs and having it decide based on, for example, mangling information.


Full diff: https://github.com/llvm/llvm-project/pull/83908.diff

2 Files Affected:

  • (modified) lldb/include/lldb/Target/Language.h (+4)
  • (modified) lldb/source/Breakpoint/BreakpointResolver.cpp (+12)
diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h
index 0cbd8a32dccd54..957c40eb7c0772 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -339,6 +339,10 @@ class Language : public PluginInterface {
 
   virtual llvm::StringRef GetInstanceVariableName() { return {}; }
 
+  virtual bool IsInterestingCtxForLineBreakpoint(const SymbolContext &) const {
+    return true;
+  }
+
 protected:
   // Classes that inherit from Language can see and modify these
 
diff --git a/lldb/source/Breakpoint/BreakpointResolver.cpp b/lldb/source/Breakpoint/BreakpointResolver.cpp
index bc6348716ef418..876b30c6d76d55 100644
--- a/lldb/source/Breakpoint/BreakpointResolver.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolver.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Language.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
@@ -199,6 +200,15 @@ bool operator<(const SourceLoc lhs, const SourceLoc rhs) {
 }
 } // namespace
 
+static void
+ApplyLanguageFilters(llvm::SmallVectorImpl<SymbolContext> &sc_list) {
+  llvm::erase_if(sc_list, [](SymbolContext &sc) {
+    if (Language *lang = Language::FindPlugin(sc.GetLanguage()))
+      return !lang->IsInterestingCtxForLineBreakpoint(sc);
+    return false;
+  });
+}
+
 void BreakpointResolver::SetSCMatchesByLine(
     SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue,
     llvm::StringRef log_ident, uint32_t line, std::optional<uint16_t> column) {
@@ -206,6 +216,8 @@ void BreakpointResolver::SetSCMatchesByLine(
   for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
     all_scs.push_back(sc_list[i]);
 
+  ApplyLanguageFilters(all_scs);
+
   while (all_scs.size()) {
     uint32_t closest_line = UINT32_MAX;
 

Some languages may create artificial functions that have no real user code, even
though there is line table information for them. One such case is with coroutine
code that receives the CoroSplitter transformation in LLVM IR. That code
transformation creates many different Functions, cloning one Instruction into
many Instructions in many different Functions and copying the associated debug
locations.

It would be difficult to make that pass delete debug locations of cloned
instructions in a language agnostic way (is it even possible?), but LLDB can
ignore certain locations by querying its Language APIs and having it decide
based on, for example, mangling information.
@jimingham
Copy link
Collaborator

LGTM except you should have a little bit of doc describing what "interesting" means. On the face of it, this seems a little silly. Why would the compiler emit "uninteresting" line table entries? Your example motivation the PR makes that clear, that or something like in the docs would help motivate this.

Also, are these 100% uninteresting line table entries? At present, there's no way to get lldb to not filter them out, so they either really need to be totally uninteresting, or we need a setting to turn them back on again.

@felipepiovezan
Copy link
Contributor Author

Also, are these 100% uninteresting line table entries? At present, there's no way to get lldb to not filter them out, so they either really need to be totally uninteresting, or we need a setting to turn them back on again.

They should be 100% uninteresting, but I agree that it would be nice to have a mechanism allowing these to be re-enabled.
Do you think it is better to have a setting for this, or could we perhaps add the breakpoint but keep it disabled by default (is there precedent for this?) ?

@jimingham
Copy link
Collaborator

jimingham commented Mar 5, 2024 via email

Comment on lines 217 to 219
all_scs.push_back(sc_list[i]);

ApplyLanguageFilters(all_scs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To repeat what @adrian-prantl said, what do you think about filtering inside this for loop, instead of filtering after the list has been constructed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I'll change that in the next iteration of this patch (it was uploaded before Adrian's comment)

@felipepiovezan felipepiovezan force-pushed the felipe/lldb_filter_language branch from 32ed570 to 7ea76d6 Compare March 6, 2024 02:49
@felipepiovezan
Copy link
Contributor Author

I believe I've addressed all the feedback here.
Tried really hard to come up with a shorter name for that target option, but could not find something both short and descriptive. If you can think of anything better, please let me know

@felipepiovezan
Copy link
Contributor Author

address review comments from Adrian.
I think I have a better name for the target option and language method now

@felipepiovezan felipepiovezan force-pushed the felipe/lldb_filter_language branch from e9fbb30 to 711ecc2 Compare March 12, 2024 23:49
Copy link
Collaborator

@jimingham jimingham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@felipepiovezan felipepiovezan merged commit 0adccd1 into llvm:main Mar 14, 2024
@felipepiovezan felipepiovezan deleted the felipe/lldb_filter_language branch March 14, 2024 16:40
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Mar 14, 2024
Some languages may create artificial functions that have no real user
code, even though there is line table information for them. One such
case is with coroutine code that receives the CoroSplitter
transformation in LLVM IR. That code transformation creates many
different Functions, cloning one Instruction into many Instructions in
many different Functions and copying the associated debug locations.

It would be difficult to make that pass delete debug locations of cloned
instructions in a language agnostic way (is it even possible?), but LLDB
can ignore certain locations by querying its Language APIs and having it
decide based on, for example, mangling information.

(cherry picked from commit 0adccd1)
felipepiovezan added a commit to felipepiovezan/llvm-project that referenced this pull request Aug 14, 2024
Some languages may create artificial functions that have no real user
code, even though there is line table information for them. One such
case is with coroutine code that receives the CoroSplitter
transformation in LLVM IR. That code transformation creates many
different Functions, cloning one Instruction into many Instructions in
many different Functions and copying the associated debug locations.

It would be difficult to make that pass delete debug locations of cloned
instructions in a language agnostic way (is it even possible?), but LLDB
can ignore certain locations by querying its Language APIs and having it
decide based on, for example, mangling information.

(cherry picked from commit 0adccd1)
(cherry picked from commit 265ab8d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants