-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
debuginfo: Captured variables and large pass-by-value arguments #8855
Conversation
This is really excellent work. 🌵 The refactoring is particularly nice! |
Thanks! |
@cmr This was a legitimate error: The Mac builds need LLVM wrapper functions to be listed in |
@jdm This failure doesn't seem to be related to my code. Please retry... |
This pull request includes * support for variables captured in closures*, * a fix for issue #8512: arguments of non-immediate type (structs, tuples, etc) passed by value can now be accessed correctly in GDB. (I managed to fix this by using `llvm::DIBuilder::createComplexVariable()`. However, I am not sure if this relies on unstable implementation details of LLVM's debug info handling. I'll try to clarify this on the LLVM mailing list). * simplification of the `debuginfo` module's public interface: the caller of functions like `create_local_var_metadata()` doesn't have to know and catch all cases when it mustn't call the function, * a cleanup refactoring with unified handling for locals, [self] arguments, captured variables, and match bindings, * and proper span information for self arguments. \* However, see comment at https://github.com/michaelwoerister/rust/blob/1d916ace136a27e354d73d65f488603c65f65bd2/src/test/debug-info/var-captured-in-nested-closure.rs#L62 . This is the same problem as with the fix for issue #8512 above: We are probably using `llvm.dbg.declare` in an unsupported way that works today but might not work after the next LLVM update. Cheers, Michael Fixes #8512 Fixes #1341
OK, I've updated this. Captured variables and complex by-value arguments are now handled "the right way". That is, the code now always provides an Note, however, that this sometimes introduces new allocas just for use by debug information. The specific cases are:
The only thing that does not yet use this more stable method is self argument descriptions. They have rather specialized handling in the code and I haven't gotten around to analyse this. |
Oh, I just noticed that this needs another rebase. |
… of self arguments)
… value. Also updated documentation comments in debuginfo and renamed DebugContext to CrateDebugContext.
@jdm rebased... |
This pull request includes * support for variables captured in closures*, * a fix for issue #8512: arguments of non-immediate type (structs, tuples, etc) passed by value can now be accessed correctly in GDB. (I managed to fix this by using `llvm::DIBuilder::createComplexVariable()`. ~~However, I am not sure if this relies on unstable implementation details of LLVM's debug info handling. I'll try to clarify this on the LLVM mailing list~~). * simplification of the `debuginfo` module's public interface: the caller of functions like `create_local_var_metadata()` doesn't have to know and catch all cases when it mustn't call the function, * a cleanup refactoring with unified handling for locals, [self] arguments, captured variables, and match bindings, * and proper span information for self arguments. \* However, see comment at https://github.com/michaelwoerister/rust/blob/1d916ace136a27e354d73d65f488603c65f65bd2/src/test/debug-info/var-captured-in-nested-closure.rs#L62 . This is the same problem as with the fix for issue #8512 above: We are probably using `llvm.dbg.declare` in an unsupported way that works today but might not work after the next LLVM update. Cheers, Michael Fixes #8512 Fixes #1341
file_metadata, | ||
loc.line as c_uint, | ||
type_metadata, | ||
cx.sess.opts.optimize != session::No, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I'm a bit late, but was this intended?
For other LLVM functions, the cx.sess.opts.optimize != session::No
argument corresponds to isOptimized: bool
, but for LLVMDIBuilderCreateLocalVariable
, it's actually AlwaysPreserve: bool
.
And AFAICT, ever setting AlwaysPreserve
to false
is asking for trouble, at least when it comes to real user variables, and we don't really use LLVM debuginfo for anything else.
cc @nikomatsakis @rkruppe (I came across this while trying to get llvm.dbg.value
to work)
rustc_codegen_llvm: always set AlwaysPreserve on all debuginfo variables Making this depend on the optimization level appears to have been a copy-paste mistake (other LLVM functions called in this module also take a `bool` argument, but there it means something unrelated). Also see #8855 (comment). I don't believe we have any reason to let LLVM omit user variables from DWARF, and we were already setting this to `true` when LLVM *could* optimize them away, so this PR should have no effect anyway. r? @michaelwoerister or @nagisa cc @rkruppe @nikomatsakis
…agisa rustc_codegen_llvm: always set AlwaysPreserve on all debuginfo variables Making this depend on the optimization level appears to have been a copy-paste mistake (other LLVM functions called in this module also take a `bool` argument, but there it means something unrelated). Also see rust-lang#8855 (comment). I don't believe we have any reason to let LLVM omit user variables from DWARF, and we were already setting this to `true` when LLVM *could* optimize them away, so this PR should have no effect anyway. r? @michaelwoerister or @nagisa cc @rkruppe @nikomatsakis
…agisa rustc_codegen_llvm: always set AlwaysPreserve on all debuginfo variables Making this depend on the optimization level appears to have been a copy-paste mistake (other LLVM functions called in this module also take a `bool` argument, but there it means something unrelated). Also see rust-lang#8855 (comment). I don't believe we have any reason to let LLVM omit user variables from DWARF, and we were already setting this to `true` when LLVM *could* optimize them away, so this PR should have no effect anyway. r? @michaelwoerister or @nagisa cc @rkruppe @nikomatsakis
…agisa rustc_codegen_llvm: always set AlwaysPreserve on all debuginfo variables Making this depend on the optimization level appears to have been a copy-paste mistake (other LLVM functions called in this module also take a `bool` argument, but there it means something unrelated). Also see rust-lang#8855 (comment). I don't believe we have any reason to let LLVM omit user variables from DWARF, and we were already setting this to `true` when LLVM *could* optimize them away, so this PR should have no effect anyway. r? @michaelwoerister or @nagisa cc @rkruppe @nikomatsakis
Add test for rust-lang#8855 Fix rust-lang#8855 Here is what I think is going on. First, the expression `format!("{:>6} {:>6}", a, b.to_string())` expands to: ```rust { let res = ::alloc::fmt::format(::core::fmt::Arguments::new_v1_formatted(&["", " "], &[::core::fmt::ArgumentV1::new_display(&a), ::core::fmt::ArgumentV1::new_display(&b.to_string())], &[::core::fmt::rt::v1::Argument { position: 0usize, format: ::core::fmt::rt::v1::FormatSpec { fill: ' ', align: ::core::fmt::rt::v1::Alignment::Right, flags: 0u32, precision: ::core::fmt::rt::v1::Count::Implied, width: ::core::fmt::rt::v1::Count::Is(6usize), }, }, ::core::fmt::rt::v1::Argument { position: 1usize, format: ::core::fmt::rt::v1::FormatSpec { fill: ' ', align: ::core::fmt::rt::v1::Alignment::Right, flags: 0u32, precision: ::core::fmt::rt::v1::Count::Implied, width: ::core::fmt::rt::v1::Count::Is(6usize), }, }], unsafe { ::core::fmt::UnsafeArg::new() })); res } ``` When I dump the expressions that get past the call to `has_string_formatting` [here](https://github.com/rust-lang/rust-clippy/blob/b312ad7d0cf0f30be2bd4658b71a3520a2e76709/clippy_lints/src/format_args.rs#L83), I see more than I would expect. In particular, I see this subexpression of the above: ``` &[::core::fmt::ArgumentV1::new_display(&a), ::core::fmt::ArgumentV1::new_display(&b.to_string())], ``` This suggests to me that more expressions are getting past [this call](https://github.com/rust-lang/rust-clippy/blob/b312ad7d0cf0f30be2bd4658b71a3520a2e76709/clippy_lints/src/format_args.rs#L71) to `FormatArgsExpn::parse` than should. Those expressions are then visited, but no `::core::fmt::rt::v1::Argument`s are found and pushed [here](https://github.com/rust-lang/rust-clippy/blob/b312ad7d0cf0f30be2bd4658b71a3520a2e76709/clippy_utils/src/macros.rs#L407). As a result, the expressions appear unformatted, hence, the false positive. My proposed fix is to restrict `FormatArgsExpn::parse` so that it only matches `Call` expressions. cc: `@akanalytics` changelog: none
This pull request includes
llvm::DIBuilder::createComplexVariable()
.However, I am not sure if this relies on unstable implementation details of LLVM's debug info handling. I'll try to clarify this on the LLVM mailing list).debuginfo
module's public interface: the caller of functions likecreate_local_var_metadata()
doesn't have to know and catch all cases when it mustn't call the function,* However, see comment at https://github.com/michaelwoerister/rust/blob/1d916ace136a27e354d73d65f488603c65f65bd2/src/test/debug-info/var-captured-in-nested-closure.rs#L62 . This is the same problem as with the fix for issue #8512 above: We are probably using
llvm.dbg.declare
in an unsupported way that works today but might not work after the next LLVM update.Cheers,
Michael
Fixes #8512
Fixes #1341