Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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<TargetFeature>,
) -> 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 {
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ symbols! {
avx512bw,
avx512f,
await_macro,
backchain,
backend_repr,
begin_panic,
bench,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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), &[]),
Comment thread
RalfJung marked this conversation as resolved.
("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), &[]),
Expand Down
6 changes: 6 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 4 additions & 17 deletions tests/assembly-llvm/s390x-backchain-toggle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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{{.*}}
}
5 changes: 3 additions & 2 deletions tests/codegen-llvm/backchain.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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"{{.*}} }
3 changes: 3 additions & 0 deletions tests/codegen-llvm/force-frame-pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
4 changes: 4 additions & 0 deletions tests/codegen-llvm/frame-pointer-cli-control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -39,6 +40,9 @@ Specific cases where platforms or tools rely on frame pointers for sound or corr
- openbsd: <https://github.com/rust-lang/rust/issues/43575>
- i686-msvc <https://github.com/rust-lang/backtrace-rs/pull/584#issuecomment-1966177530>
- i686-mingw: <https://github.com/rust-lang/rust/commit/3f1d3948d6d434b34dd47f132c126a6cb6b8a4ab>

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]
Expand Down
1 change: 0 additions & 1 deletion tests/ui/check-cfg/target_feature.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`avxvnniint16`
`avxvnniint8`
`b`
`backchain`
`bf16`
`bmi1`
`bmi2`
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/target-feature/forbidden-target-feature-backchain.rs
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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

This file was deleted.

This file was deleted.

21 changes: 8 additions & 13 deletions tests/ui/target-feature/packedstack-combinations.rs
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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)
Loading