Skip to content
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

Use call instead of invoke for functions that cannot unwind #70467

Merged
merged 1 commit into from
Apr 18, 2020

Conversation

wesleywiser
Copy link
Member

@wesleywiser wesleywiser commented Mar 27, 2020

The FnAbi now knows if the function is allowed to unwind. If a
function isn't allowed to unwind, we can use a call instead of an
invoke.

This resolves an issue when calling LLVM intrinsics which cannot unwind
LLVM will generate an error if you attempt to invoke them so we need to
ignore cleanup blocks in codegen and generate a call instead.

Fixes #69911

r? @eddyb
cc @rust-lang/wg-ffi-unwind

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 27, 2020
@nikic
Copy link
Contributor

nikic commented Mar 27, 2020

There are some LLVM intrinsics that do support invokes, you can find the list at https://github.com/llvm/llvm-project/blob/30a8b77080b98ffdd1837d2ea2e74f91e40cc867/llvm/lib/IR/Verifier.cpp#L4164-L4175. Apart from maybe the wasm one, probably nothing that's relevant to Rust.

As a side-note, LLVM intrinsics should always use the "unadjusted" ABI, something that is not happening right now.

src/librustc/ty/layout.rs Outdated Show resolved Hide resolved
src/librustc/ty/layout.rs Outdated Show resolved Hide resolved
src/librustc/ty/layout.rs Outdated Show resolved Hide resolved
@eddyb
Copy link
Member

eddyb commented Mar 27, 2020

I think this PR is branded as fixing a bug, but it's changing a lot about how nounwind is computed and works, so it should be rebranded or split into two PRs.

@nikic I think those intrinsics (if ever used directly from a library, which we should've never allowed, but that's another discussion) should be marked explicitly with #[unwind].

@rust-highfive

This comment has been minimized.

@wesleywiser
Copy link
Member Author

@nikic I think those intrinsics (if ever used directly from a library, which we should've never allowed, but that's another discussion) should be marked explicitly with #[unwind].

I agree. I wouldn't want to maintain a list of unwinding intrinsics in rustc and using #[unwind] on those would work.

@bors
Copy link
Contributor

bors commented Mar 30, 2020

☔ The latest upstream changes (presumably #70536) made this pull request unmergeable. Please resolve the merge conflicts.

mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
) -> Self;
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
}

fn can_unwind(
Copy link
Member

Choose a reason for hiding this comment

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

If this logic now lives in librustc, that might help with #65303.

Centril added a commit to Centril/rust that referenced this pull request Apr 1, 2020
…ddyb

Add `can_unwind` field to `FnAbi`

This is a pure refactoring with no behavior changes.

Extracted out of rust-lang#70467

r? @eddyb
Centril added a commit to Centril/rust that referenced this pull request Apr 1, 2020
…ddyb

Add `can_unwind` field to `FnAbi`

This is a pure refactoring with no behavior changes.

Extracted out of rust-lang#70467

r? @eddyb
@joelpalmer joelpalmer added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 9, 2020
@Dylan-DPC-zz Dylan-DPC-zz added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 9, 2020
The `FnAbi` now knows if the function is allowed to unwind. If a
function isn't allowed to unwind, we can use a `call` instead of an
`invoke`.

This resolves an issue when calling LLVM intrinsics which cannot unwind
LLVM will generate an error if you attempt to invoke them so we need to
ignore cleanup blocks in codegen and generate a call instead.
@wesleywiser wesleywiser changed the title Use call instead of invoke on LLVM intrinsics Use call instead of invoke for functions that cannot unwind Apr 15, 2020
@wesleywiser
Copy link
Member Author

I believe this is ready for review.

@eddyb
Copy link
Member

eddyb commented Apr 16, 2020

r? @nagisa (LGTM, but I'm not sure if this is going to affect some ongoing ffi-unwind stuff)

@rust-highfive rust-highfive assigned nagisa and unassigned eddyb Apr 16, 2020
Copy link
Member

@nagisa nagisa left a comment

Choose a reason for hiding this comment

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

r=me after at least an issue is filled about not generating cleanup blocks in the first place.

if let Some(cleanup) = cleanup {
// If there is a cleanup block and the function we're calling can unwind, then
// do an invoke, otherwise do a call.
if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
Copy link
Member

Choose a reason for hiding this comment

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

IMO in most instances this should happen way earlier. That is, the cleanup blocks should not be reach codegen in the first place for calls of functions that cannot unwind. This can happen either during MIR construction or afterwards in some clean-up pass.

This piece of code still needs to exist, of course, because fn_abi information in some cases may only be available after monomorphization, but the test case that changes in this PR does not involve generics...

I’m fine with work to do this happening in some follow-up PR (possibly implemented by somebody else), but in that case at least an issue needs to exist to that effect.

@BatmanAoD
Copy link
Member

@eddyb @Amanieu will this cause us to use call for any pthread-cancelable functions? Otherwise, AFAIK it should not be a problem from the perspective of FFI-unwind.

@Amanieu
Copy link
Member

Amanieu commented Apr 16, 2020

@BatmanAoD It doesn't matter since unwinding from extern "C" is UB. pthread cancellation uses unwinding at first and then switches to longjmp if it can't find unwind info for a frame. The only valid way to use these functions is to assume they longjmp and avoid any destructors in frame that they unwind.

@wesleywiser
Copy link
Member Author

@bors r=nagisa

@bors
Copy link
Contributor

bors commented Apr 17, 2020

📌 Commit 8da26e0 has been approved by nagisa

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 17, 2020
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 17, 2020
Use `call` instead of `invoke` for functions that cannot unwind

The `FnAbi` now knows if the function is allowed to unwind. If a
function isn't allowed to unwind, we can use a `call` instead of an
`invoke`.

This resolves an issue when calling LLVM intrinsics which cannot unwind
LLVM will generate an error if you attempt to invoke them so we need to
ignore cleanup blocks in codegen and generate a call instead.

Fixes rust-lang#69911

r? @eddyb
cc @rust-lang/wg-ffi-unwind
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 17, 2020
Rollup of 6 pull requests

Successful merges:

 - rust-lang#70467 (Use `call` instead of `invoke` for functions that cannot unwind )
 - rust-lang#71070 (rustbuild: Remove stage 0 LLD flavor workaround for MSVC)
 - rust-lang#71167 (big-O notation: parenthesis for function calls, explicit multiplication)
 - rust-lang#71238 (Miri: fix typo)
 - rust-lang#71242 (Format Mailmap To Work With GitHub)
 - rust-lang#71243 (Account for use of `try!()` in 2018 edition and guide users in the right direction)

Failed merges:

r? @ghost
@bors bors merged commit 43cf9d7 into rust-lang:master Apr 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect LLVM generated with mir-opt-level=2: cannot invoke intrinsic