diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 4073d521293a9..f42baf5d80838 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -222,7 +222,11 @@ pub(crate) fn frame_pointer(sess: &Session) -> FramePointer { if let InstrumentMcount::Mcount(_) = opts.unstable_opts.instrument_mcount { fp.ratchet(FramePointer::Always); } - fp.ratchet(opts.cg.force_frame_pointers); + // On s390x, `-Cforce-frame-pointers` opts in to the `backchain` LLVM function attribute + // (set in `s390x_fn_attrs`) instead of the generic `frame-pointer` attribute. + if !(sess.target.arch == Arch::S390x) { + fp.ratchet(opts.cg.force_frame_pointers); + } fp } @@ -396,34 +400,44 @@ fn stackprotector_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll A Some(sspattr.create_attr(cx.llcx)) } -fn packed_stack_attr<'ll>( +/// s390x specific function attributes +/// - `-Cforce-frame-pointers` emits "backchain" +/// - "backchain" + "packed_stack" enforces "softfloat" +fn s390x_fn_attrs<'ll>( cx: &SimpleCx<'ll>, sess: &Session, - function_attributes: &Vec, -) -> Option<&'ll Attribute> { + fn_target_features: &[TargetFeature], +) -> Vec<&'ll Attribute> { if sess.target.arch != Arch::S390x { - return None; + return vec![]; + } + + let mut attrs = Vec::new(); + + // `-Cforce-frame-pointers` enables `backchain` + let have_backchain = sess.opts.cg.force_frame_pointers != FramePointer::MayOmit; + if have_backchain { + attrs.push(llvm::CreateAttrString(cx.llcx, "backchain")); } + + // only continue if we have packed_stack if !sess.opts.unstable_opts.packed_stack { - return None; + return attrs; } - // The backchain and softfloat flags can be set via -Ctarget-features=... - // or via #[target_features(enable = ...)] so we have to check both possibilities - let have_backchain = sess.internal_target_features.contains(&sym::backchain) - || function_attributes.iter().any(|feature| feature.name == sym::backchain); let have_softfloat = sess.internal_target_features.contains(&sym::soft_float) - || function_attributes.iter().any(|feature| feature.name == sym::soft_float); + || fn_target_features.iter().any(|f| f.name == sym::soft_float); // If both, backchain and packedstack, are enabled LLVM cannot generate valid function entry points // with the default ABI. However if the softfloat flag is set LLVM will switch to the softfloat // ABI, where this works. if have_backchain && !have_softfloat { sess.dcx().emit_err(PackedStackBackchainNeedsSoftfloat); - return None; + return attrs; } - Some(llvm::CreateAttrString(cx.llcx, "packed-stack")) + attrs.push(llvm::CreateAttrString(cx.llcx, "packed-stack")); + attrs } pub(crate) fn target_cpu_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> &'ll Attribute { @@ -650,9 +664,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( if let Some(align) = codegen_fn_attrs.alignment { llvm::set_alignment(llfn, align); } - if let Some(packed_stack) = packed_stack_attr(cx, sess, &codegen_fn_attrs.target_features) { - to_add.push(packed_stack); + + // Apply and check s390x-specific attributes: backchain and packed-stack. + if sess.target.arch == Arch::S390x { + to_add.extend(s390x_fn_attrs(cx, sess, &codegen_fn_attrs.target_features)); } + to_add.extend(patchable_function_entry_attrs( cx, sess, diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 08b96770e46d1..a06f22310c310 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -227,9 +227,9 @@ pub(crate) struct FixedX18InvalidArch<'a> { } #[derive(Diagnostic)] -#[diag("`-Zpacked-stack` is incompatible with `backchain` target feature")] +#[diag("`-Zpacked-stack` is incompatible with `-Cforce-frame-pointers` on s390x")] #[note( - "enabling both `-Zpacked-stack` and the `backchain` target feature is incompatible with the default s390x ABI. Switch to s390x-unknown-none-softfloat if you need both attributes" + "`-Zpacked-stack` and `-Cforce-frame-pointers` is incompatible with the default s390x ABI (note that force-frame-pointers is implemented via backchain)" )] pub(crate) struct PackedStackBackchainNeedsSoftfloat; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3debf3248ff80..57c20a8d610ff 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -542,7 +542,6 @@ symbols! { avx512bw, avx512f, await_macro, - backchain, backend_repr, begin_panic, bench, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 2ee7dea9f8af3..2ee73bf9fadd5 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -937,7 +937,7 @@ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start // For "backchain", https://github.com/rust-lang/rust/issues/142412 is a stabilization blocker - ("backchain", Unstable(sym::s390x_target_feature), &[]), + ("backchain", InternalOnly { reason: "use `-Cforce-frame-pointers` compiler flag instead", hard_error: true }, &[]), ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]), ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]), ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]), diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 0f85e6d00e36b..7a8a1ba7e3c76 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -170,6 +170,12 @@ values: The default behaviour, if frame pointers are not force-enabled, depends on the target. +#### Implementation notes + +On s390x targets, frame pointers cannot be used to walk the stack. Instead of enabling frame +pointers, this flag enables the `backchain`, which stores a pointer to the caller's frame in each +function's frame. + ## force-unwind-tables This flag forces the generation of unwind tables. It takes one of the following diff --git a/tests/assembly-llvm/s390x-backchain-toggle.rs b/tests/assembly-llvm/s390x-backchain-toggle.rs index baf7104727833..bc602d1baec8c 100644 --- a/tests/assembly-llvm/s390x-backchain-toggle.rs +++ b/tests/assembly-llvm/s390x-backchain-toggle.rs @@ -3,8 +3,8 @@ //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu //@ needs-llvm-components: systemz -//@[enable-backchain] compile-flags: -Ctarget-feature=+backchain -//@[disable-backchain] compile-flags: -Ctarget-feature=-backchain +//@[enable-backchain] compile-flags: -Cforce-frame-pointers +//@[disable-backchain] compile-flags: -Cforce-frame-pointers=no #![feature(no_core, lang_items)] #![no_std] #![no_core] @@ -31,20 +31,7 @@ extern "C" fn test_backchain() -> i32 { unsafe { extern_func(); } - // enable-backchain-NEXT: brasl %r{{.*}}, extern_func@PLT - // disable-backchain: brasl %r{{.*}}, extern_func@PLT - - // Make sure that the expected return value is written into %r2 (return register): - // enable-backchain-NEXT: lghi %r2, 1 - // disable-backchain: lghi %r2, 0 - // default-backchain: lghi %r2, 0 - #[cfg(target_feature = "backchain")] - { - 1 - } - #[cfg(not(target_feature = "backchain"))] - { - 0 - } + // NEXT: brasl %r{{.*}}, extern_func@PLT + 1 // CHECK: br %r{{.*}} } diff --git a/tests/codegen-llvm/backchain.rs b/tests/codegen-llvm/backchain.rs index fae494dcad1b4..1cb01f3cf0032 100644 --- a/tests/codegen-llvm/backchain.rs +++ b/tests/codegen-llvm/backchain.rs @@ -1,5 +1,6 @@ //@ add-minicore -//@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu -Ctarget-feature=+backchain +//@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu +//@ compile-flags: -Cforce-frame-pointers=yes //@ needs-llvm-components: systemz #![crate_type = "lib"] #![feature(no_core, lang_items)] @@ -12,4 +13,4 @@ use minicore::*; pub fn test_backchain() { // CHECK: @test_backchain() unnamed_addr #0 } -// CHECK: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+backchain{{.*}} } +// CHECK: attributes #0 = { {{.*}}"backchain"{{.*}} } diff --git a/tests/codegen-llvm/force-frame-pointers.rs b/tests/codegen-llvm/force-frame-pointers.rs index 2cdc37e691115..1d7cb2bea60aa 100644 --- a/tests/codegen-llvm/force-frame-pointers.rs +++ b/tests/codegen-llvm/force-frame-pointers.rs @@ -9,6 +9,9 @@ //@ [NonLeaf] ignore-x86_64-apple-darwin //@ [NonLeaf] ignore-windows-gnu //@ [NonLeaf] ignore-thumb +// On s390x, -Cforce-frame-pointers emits `"backchain"` not `"frame-pointer"`. +// Since this test passes -Zunstable-options globally, it must be skipped on s390x. +//@ ignore-s390x // result is platform-dependent based on platform's frame pointer settings #![crate_type = "lib"] diff --git a/tests/codegen-llvm/frame-pointer-cli-control.rs b/tests/codegen-llvm/frame-pointer-cli-control.rs index 79cdfc70f1ad7..47b2464bcd07c 100644 --- a/tests/codegen-llvm/frame-pointer-cli-control.rs +++ b/tests/codegen-llvm/frame-pointer-cli-control.rs @@ -2,6 +2,7 @@ //@ compile-flags: --crate-type=rlib -Copt-level=0 //@ revisions: force-on aarch64-apple aarch64-apple-on aarch64-apple-off //@ [force-on] compile-flags: -Cforce-frame-pointers=on +//@ [force-on] ignore-s390x //@ [aarch64-apple] needs-llvm-components: aarch64 //@ [aarch64-apple] compile-flags: --target=aarch64-apple-darwin //@ [aarch64-apple-on] needs-llvm-components: aarch64 @@ -39,6 +40,9 @@ Specific cases where platforms or tools rely on frame pointers for sound or corr - openbsd: - i686-msvc - i686-mingw: + +S390x is a special case because on this platform framepointers cannot be use for unwinding. +On s390x `-Cforce-frame-pointers=on' will emit a 'backchain' attribute which is tested elsewhere. */ #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 13c49fe00ef1f..ca6fdd4995c2a 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -56,7 +56,6 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `avxvnniint16` `avxvnniint8` `b` -`backchain` `bf16` `bmi1` `bmi2` diff --git a/tests/ui/target-feature/forbidden-target-feature-backchain.rs b/tests/ui/target-feature/forbidden-target-feature-backchain.rs new file mode 100644 index 0000000000000..b868352321e6c --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-backchain.rs @@ -0,0 +1,10 @@ +//! Ensure `backchain` cannot be enabled via `-Ctarget-feature` on s390x. +//@ compile-flags: --crate-type=lib --target=s390x-unknown-linux-gnu +//@ compile-flags: -Ctarget-feature=+backchain +//@ needs-llvm-components: systemz +//@ ignore-backends: gcc + +#![feature(no_core)] +#![no_core] + +//~? ERROR target feature `backchain` cannot be enabled with `-Ctarget-feature`: use `-Cforce-frame-pointers` compiler flag instead diff --git a/tests/ui/target-feature/forbidden-target-feature-backchain.stderr b/tests/ui/target-feature/forbidden-target-feature-backchain.stderr new file mode 100644 index 0000000000000..38847e3d8fe4e --- /dev/null +++ b/tests/ui/target-feature/forbidden-target-feature-backchain.stderr @@ -0,0 +1,4 @@ +error: target feature `backchain` cannot be enabled with `-Ctarget-feature`: use `-Cforce-frame-pointers` compiler flag instead + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/packedstack-combinations.backchain_attr.stderr b/tests/ui/target-feature/packedstack-combinations.backchain_attr.stderr deleted file mode 100644 index 6270e43e93255..0000000000000 --- a/tests/ui/target-feature/packedstack-combinations.backchain_attr.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: `-Zpacked-stack` is incompatible with `backchain` target feature - | - = note: enabling both `-Zpacked-stack` and the `backchain` target feature is incompatible with the default s390x ABI. Switch to s390x-unknown-none-softfloat if you need both attributes - -error: aborting due to 1 previous error - diff --git a/tests/ui/target-feature/packedstack-combinations.need_softfloat.stderr b/tests/ui/target-feature/packedstack-combinations.need_softfloat.stderr deleted file mode 100644 index 6f4531945ee07..0000000000000 --- a/tests/ui/target-feature/packedstack-combinations.need_softfloat.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `backchain` - | - = note: this feature is not stably supported; its behavior can change in the future - -error: packedstack with backchain needs softfloat - | - = note: enabling both `-Zpacked-stack` and the `backchain` target feature is incompatible with the default s390x ABI. Switch to s390x-unknown-none-softfloat if you need both attributes - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/target-feature/packedstack-combinations.rs b/tests/ui/target-feature/packedstack-combinations.rs index dc45ac1ff5e83..4898cc6ba672e 100644 --- a/tests/ui/target-feature/packedstack-combinations.rs +++ b/tests/ui/target-feature/packedstack-combinations.rs @@ -1,5 +1,6 @@ +// backchain on s390x is enabled with -Cforce-frame-pointers //@ add-minicore -//@ revisions: wrong_arch only_packedstack backchain_attr backchain_cli with_softfloat +//@ revisions: wrong_arch only_packedstack backchain_cli with_softfloat //@ compile-flags: -Zpacked-stack --crate-type=rlib //@ ignore-backends: gcc @@ -11,32 +12,26 @@ //@ [only_packedstack] build-pass //@ [only_packedstack] needs-llvm-components: systemz -//@ [backchain_attr] compile-flags: --target=s390x-unknown-linux-gnu -//@ [backchain_attr] build-fail -//@ [backchain_attr] needs-llvm-components: systemz - -//@ [backchain_cli] compile-flags: -Ctarget-feature=+backchain --target=s390x-unknown-linux-gnu +//@ [backchain_cli] compile-flags: --target=s390x-unknown-linux-gnu +//@ [backchain_cli] compile-flags: -Cforce-frame-pointers //@ [backchain_cli] should-fail //@ [backchain_cli] needs-llvm-components: systemz -//@ [with_softfloat] compile-flags: -Ctarget-feature=+backchain +//@ [with_softfloat] compile-flags: -Cforce-frame-pointers //@ [with_softfloat] compile-flags: --target=s390x-unknown-none-softfloat //@ [with_softfloat] build-pass //@ [with_softfloat] needs-llvm-components: systemz #![feature(s390x_target_feature)] #![crate_type = "rlib"] -#![feature(no_core,lang_items)] +#![feature(no_core, lang_items)] #![no_core] extern crate minicore; use minicore::*; #[no_mangle] -#[cfg_attr(backchain_attr,target_feature(enable = "backchain"))] -pub fn test() { -} +pub fn test() {} //[wrong_arch]~? ERROR `-Zpacked-stack` is only supported on s390x -//[backchain_cli]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature -//[backchain_attr]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature +//[backchain_cli]~? ERROR `-Zpacked-stack` is incompatible with `-Cforce-frame-pointers` (backchain)