Skip to content

Dyno: add backtracing LLDB script #26944

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 2 commits into from
Mar 21, 2025
Merged

Conversation

DanilaFe
Copy link
Contributor

@DanilaFe DanilaFe commented Mar 19, 2025

LLDB exposes a convenient Python API. We can leverage this API to print clean stacktaces while resolving Dyno programs. See also my comment in the file.

Dyno stack trace script.

Though Dyno often performs re-computation, it's typical for the
compiler stacktrace to mirror (with a lot of function calls) the trace of
resolving the Chapel program. We can clean up this information, skipping
a lot of in-between frames, and print a Chapel-only trace. That's what this
script does.

To use the script, add the following lines to your .lldbinit file:

    command script import /path/to/dyno_backtrace.py
    command script add -f dyno_backtrace.backtrace dbt

Then, in the debugger, you can run the `dbt` command to print the Chapel
stack trace.

The output looks like this:

(lldb) dbt
 0: chpl__buildDomainRuntimeType at input.chpl:3 (lldb frame 152)
 1: init at /modules/internal/ChapelDomain.chpl:110 (lldb frame 137)
 2: newAssociativeDom at /modules/internal/ChapelDomain.chpl:1117 (lldb frame 118)
 3: dsiNewAssociativeDom at /modules/internal/ChapelDistribution.chpl:115 (lldb frame 103)
 4: init at /modules/internal/DefaultRectangular.chpl:110 (lldb frame 88)
 5: init at /modules/internal/DefaultAssociative.chpl:96 (lldb frame 69)
 6: init= at /modules/internal/ChapelHashtable.chpl:260 (lldb frame 45)
 7: chpl__promotionType at /modules/internal/OwnedObject.chpl:40 (lldb frame 27)
 8: borrow at /modules/internal/OwnedObject.chpl:49 (lldb frame 13)

Reviewed by @arifthpe -- thanks!

Signed-off-by: Danila Fedorin <[email protected]>
@arifthpe arifthpe self-requested a review March 19, 2025 20:03
Copy link
Contributor

@arifthpe arifthpe left a comment

Choose a reason for hiding this comment

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

Lgtm, but I'm not familiar with the LLDB api so it's a pretty basic review.

Why not add this to compiler/etc/lldb.commands and have it loaded in chpl --lldb by default?

@DanilaFe
Copy link
Contributor Author

it would be of limited utility in chpl --lldb (since, without --dyno, it doesn't use the dyno resolver), but I see no harm in adding it.

@DanilaFe
Copy link
Contributor Author

Actually, because I am not sure how this will work when the switch is thrown outside of the "usual" developer environment (e.g., what if a homebrew install throws --lldb?), I'd rather not mess with the commands file.

@DanilaFe DanilaFe merged commit c7638b4 into chapel-lang:main Mar 21, 2025
9 checks passed
@DanilaFe DanilaFe requested a review from Copilot April 4, 2025 18:35
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

util/devel/dyno_backtrace.py:50

  • [nitpick] Using magic indices for accessing frame variables (e.g., index 0, 1, and 3) makes the code less clear; consider introducing descriptive variable names or constants to document the expected variable roles.
rc = frame.variables[0]

Comment on lines +21 to +23
def get_child_by_name(value, name):
return next(child for child in value.children if child.name == name)

Copy link
Preview

Copilot AI Apr 4, 2025

Choose a reason for hiding this comment

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

The function get_child_by_name assumes that a child with the specified name exists, which may result in a StopIteration error if not found. Consider adding error handling or a default value.

Suggested change
def get_child_by_name(value, name):
return next(child for child in value.children if child.name == name)
def get_child_by_name(value, name, default=None):
try:
return next(child for child in value.children if child.name == name)
except StopIteration:
if default is not None:
return default
raise ValueError(f"Child with name '{name}' not found")

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants