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

Add a bunch of rustc_nounwind for c_unwind #578

Closed
wants to merge 5 commits into from

Conversation

DianQK
Copy link
Member

@DianQK DianQK commented Feb 25, 2024

This PR fixes encountered dependency core issue in rust-lang/rust#116088.

After enabling c_unwind, consider the following code.

#![feature(c_unwind)]

#[no_mangle]
extern "C" fn foo() {
    unsafe {
        bar();
    }
}

extern "Rust" {
    fn bar();
}

Due to the lack of inlining or rustc_nounwind for bar, the core::panicking::panic_cannot_unwind function is called.

foo:
  push rax
  call qword ptr [rip + bar@GOTPCREL]
  pop rax
  ret
  call qword ptr [rip + core::panicking::panic_cannot_unwind@GOTPCREL]

Godbolt: https://rust.godbolt.org/z/Ea4rhfWcr.

In this PR, I'm checking if there are any undefined symbols belonging to core in the release build. I believe checking the debug build is meaningless. First, we won't distribute the debug build of compiler-builtins, and second, it has a lot of dependencies on core.

Since we're already checking for undefined symbols in core, I think checking the intrinsics example might not be meaningful anymore.

r? @Amanieu

@bjorn3
Copy link
Member

bjorn3 commented Feb 25, 2024

Is mir inlining enough here or does it depend on LLVM's inliner?

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

Is mir inlining enough here or does it depend on LLVM's inliner?

I think any one of them should work.

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

Is mir inlining enough here or does it depend on LLVM's inliner?

Or are you referring to using -Zinline-mir-threshold=n? Or perhaps I missed some configuration information?

@DianQK

This comment was marked as abuse.

@DianQK DianQK force-pushed the c_unwind_inline_always branch 2 times, most recently from 239b876 to 39c2086 Compare February 25, 2024 09:23
@bjorn3
Copy link
Member

bjorn3 commented Feb 25, 2024

My question is if the inlining done by the MIR inliner is enough to fix this issue or if it depends on the codegen backend inlining too. AFAIK it is possible for the MIR inliner bail out on #[inline(always)] in some cases even when LLVM's inliner would still be able to inline.

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

My question is if the inlining done by the MIR inliner is enough to fix this issue or if it depends on the codegen backend inlining too. AFAIK it is possible for the MIR inliner bail out on #[inline(always)] in some cases even when LLVM's inliner would still be able to inline.

I might understand now. We want it to work on Cranelift and GCC as well. Let me see if there is a way to experiment with it.

@RalfJung
Copy link
Member

In case we do not actually want to inline some of these functions, marking them #[rustc_nounwind] should also help.

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

My question is if the inlining done by the MIR inliner is enough to fix this issue or if it depends on the codegen backend inlining too. AFAIK it is possible for the MIR inliner bail out on #[inline(always)] in some cases even when LLVM's inliner would still be able to inline.

Godbolt: https://rust.godbolt.org/z/foe7s6ao1.

Currently, I'm not sure besides modifying LLVM code what other validation methods exist.

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

In case we do not actually want to inline some of these functions, marking them #[rustc_nounwind] should also help.

Thanks. That's what I'm looking for. I thought it was written as extern "rustc-nounwind" fn foo.

@DianQK DianQK changed the title Add a bunch of inline(always) for c_unwind Add a bunch of rustc_nounwind for c_unwind Feb 25, 2024
@Amanieu
Copy link
Member

Amanieu commented Feb 25, 2024

If I understand correctly, this attribute needs to be applied to all fn defined in compiler-builtins? At this point wouldn't it be easier to do this in the compiler by checking self.tcx.is_compiler_builtins(LOCAL_CRATE)? This would solve the problem in a single place instead of having attributes peppered around the compiler_builtins code.

@@ -93,15 +96,18 @@ if [ -z "$DEBUG_LTO_BUILD_DOESNT_WORK" ]; then
RUSTFLAGS="-C debug-assertions=no" \
CARGO_INCREMENTAL=0 \
CARGO_PROFILE_DEV_LTO=true \
$cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics
$cargo rustc --features "$INTRINSICS_FEATURES" --target $1 --example intrinsics --release
Copy link
Member

Choose a reason for hiding this comment

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

This should not have --release: this test specifically checks that debug builds (-Copt-level=0) do not reference any symbols in core. This is needed for people using -Z build-std without --release.

Copy link
Member Author

Choose a reason for hiding this comment

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

So I understand that we might expect that only compiler-builtins is optimized.

@RalfJung
Copy link
Member

If I understand correctly, this attribute needs to be applied to all fn defined in compiler-builtins? At this point wouldn't it be easier to do this in the compiler by checking self.tcx.is_compiler_builtins(LOCAL_CRATE)? This would solve the problem in a single place instead of having attributes peppered around the compiler_builtins code.

I was thinking of a crate-level version of #[rustc_nounwind]. But I also didn't know this crate already was so magic that tcx knows about it.

@nbdd0121
Copy link
Contributor

If I understand correctly, this attribute needs to be applied to all fn defined in compiler-builtins? At this point wouldn't it be easier to do this in the compiler by checking self.tcx.is_compiler_builtins(LOCAL_CRATE)? This would solve the problem in a single place instead of having attributes peppered around the compiler_builtins code.

Good point. I'll have a try with this approach.

@RalfJung
Copy link
Member

RalfJung commented Feb 25, 2024 via email

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

If I understand correctly, this attribute needs to be applied to all fn defined in compiler-builtins? At this point wouldn't it be easier to do this in the compiler by checking self.tcx.is_compiler_builtins(LOCAL_CRATE)? This would solve the problem in a single place instead of having attributes peppered around the compiler_builtins code.

I was thinking of a crate-level version of #[rustc_nounwind]. But I also didn't know this crate already was so magic that tcx knows about it.

I've tried this and it doesn't seem to work.

@DianQK
Copy link
Member Author

DianQK commented Feb 25, 2024

Sounds good! Make sure to only apply it to definitions though, not declarations.

I have found that if I add to trait it causes problems.

bors added a commit to rust-lang-ci/rust that referenced this pull request Feb 26, 2024
Mark all functions defined in compiler-builtins as nounwind

Treat functions in compiler-builtins as nounwind. Suggested in rust-lang/compiler-builtins#578 (comment).

A prerequisite for rust-lang#116088

r? `@Amanieu`
cc `@RalfJung`
@RalfJung
Copy link
Member

RalfJung commented Feb 26, 2024

I was thinking of a crate-level version of #[rustc_nounwind]. But I also didn't know this crate already was so magic that tcx knows about it.

I've tried this and it doesn't seem to work.

Yes, it's not implemented in the compiler (yet). I was proposing to implement it. (Sorry if that was not clear).

But @nbdd0121 is on the case already: rust-lang/rust#121605.

@DianQK
Copy link
Member Author

DianQK commented Feb 26, 2024

I was thinking of a crate-level version of #[rustc_nounwind]. But I also didn't know this crate already was so magic that tcx knows about it.

I've tried this and it doesn't seem to work.

Yes, it's not implemented in the compiler (yet). I was proposing to implement it. (Sorry if that was not clear).

But @nbdd0121 is on the case already: rust-lang/rust#121605.

We can consider implementing it when we encounter it again.

@DianQK
Copy link
Member Author

DianQK commented Feb 26, 2024

Prefer rust-lang/rust#121605.

@DianQK DianQK closed this Feb 26, 2024
@DianQK DianQK deleted the c_unwind_inline_always branch February 26, 2024 14:44
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.

5 participants