diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f5eb9c10db996..c2d349ac567e1 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -312,6 +312,18 @@ fn backchain_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attrib if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None } } +fn packed_stack_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attribute> { + if sess.target.arch != Arch::S390x { + return None; + } + + if sess.opts.unstable_opts.packed_stack { + Some(llvm::CreateAttrString(cx.llcx, "packed-stack")) + } else { + None + } +} + pub(crate) fn target_cpu_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> &'ll Attribute { let target_cpu = llvm_util::target_cpu(sess); llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu) @@ -533,6 +545,9 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( if let Some(backchain) = backchain_attr(cx, sess) { to_add.push(backchain); } + if let Some(packed_stack) = packed_stack_attr(cx, sess) { + to_add.push(packed_stack); + } to_add.extend(patchable_function_entry_attrs( cx, sess, diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 7e4671889f57f..00ece256de4c0 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -114,6 +114,13 @@ pub struct IgnoringOutDir; #[diag("can't use option `-o` or `--emit` to write multiple output types to stdout")] pub struct MultipleOutputTypesToStdout; +#[derive(Diagnostic)] +#[diag("packedstack with backchain needs softfloat")] +#[note( + "enabling both `packedstack` and `backchain` attributes is incompatible with the default s390x target. Switch to s390x-unknown-none-softfloat if you need both attributes!" +)] +pub struct PackedStackBackchainNeedsSoftfloat; + #[derive(Diagnostic)] #[diag( "target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly" diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 458e7ad321433..f6dc3fd6b94f9 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -25,7 +25,7 @@ use rustc_session::{EarlyDiagCtxt, Session, filesearch}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; use rustc_span::{SessionGlobals, Symbol, sym}; -use rustc_target::spec::Target; +use rustc_target::spec::{Abi, Arch, Target}; use tracing::info; use crate::errors; @@ -96,6 +96,16 @@ pub(crate) fn check_abi_required_features(sess: &Session) { sess.dcx().emit_warn(errors::AbiRequiredTargetFeature { feature, enabled: "disabled" }); } } + + // we need to have access to the complete constructed `target` and the session options. + // this is the first place in the `run_compiler` flow where all this is available + if sess.target.arch == Arch::S390x + && sess.opts.unstable_opts.packed_stack + && sess.unstable_target_features.contains(&Symbol::intern(&"backchain")) + && sess.target.abi != Abi::SoftFloat + { + sess.dcx().emit_err(errors::PackedStackBackchainNeedsSoftfloat); + } } pub static STACK_SIZE: OnceLock = OnceLock::new(); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 0c6a33f228082..c8aa1130e66c3 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -537,3 +537,7 @@ pub(crate) struct UnexpectedBuiltinCfg { pub(crate) cfg_name: Symbol, pub(crate) controlled_by: &'static str, } + +#[derive(Diagnostic)] +#[diag("`-Zpacked-stack` is only supported on s390x")] +pub(crate) struct UnsupportedPackedStack; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9219b5a7e8aca..790a5af6344d4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2536,6 +2536,8 @@ options! { "pass `-install_name @rpath/...` to the macOS linker (default: no)"), packed_bundled_libs: bool = (false, parse_bool, [TRACKED], "change rlib format to store native libraries as archives"), + packed_stack: bool = (false, parse_bool, [TRACKED], + "use packed stack frames (s390x only) (default: no)"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], "support compiling tests with panic=abort (default: no)"), panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ed37e9e960cd8..0706bad9fac8e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1348,6 +1348,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.dcx().emit_warn(errors::SoftFloatIgnored); } } + + if sess.opts.unstable_opts.packed_stack { + if sess.target.arch != Arch::S390x { + sess.dcx().emit_err(errors::UnsupportedPackedStack); + } + } } /// Holds data on the current incremental compilation session, if there is one. diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f0f991ed0c909..f10fc5118e40f 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -487,6 +487,11 @@ one of the following values: If not specified, overflow checks are enabled if [debug-assertions](#debug-assertions) are enabled, disabled otherwise. +## packed-stack + +This flag enables packed StackFrames on s390x. Enabling both `packed-stack` and `backchain` attributes is incompatible +with the default s390x target. Switch to s390x-unknown-none-softfloat if you need both attributes. + ## panic This option lets you control what happens when the code panics. diff --git a/tests/assembly-llvm/s390x-packedstack-toggle.rs b/tests/assembly-llvm/s390x-packedstack-toggle.rs new file mode 100644 index 0000000000000..d53f98baaeebe --- /dev/null +++ b/tests/assembly-llvm/s390x-packedstack-toggle.rs @@ -0,0 +1,37 @@ +//@ add-minicore +//@ revisions: enable-packedstack default-packedstack +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu -Cforce-unwind-tables=no +//@ needs-llvm-components: systemz +//@[enable-packedstack] compile-flags: -Zpacked-stack +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn extern_func() -> i32; +} + +// CHECK-LABEL: test_packedstack +#[no_mangle] +extern "C" fn test_packedstack() -> i32 { + // test the creation of call stack with and without packed-stack + + // without packed-stack we always reserve a least the maximal space of 160 bytes + // default-packedstack: stmg %r14, %r15, 112(%r15) + // default-packedstack-NEXT: aghi %r15, -160 + // default-packedstack-NEXT: brasl %r14, extern_func + + // with packed-stack only the actually needed registers are reserved on the stack + // enable-packedstack: stmg %r14, %r15, 144(%r15) + // enable-packedstack-NEXT: aghi %r15, -16 + // enable-packedstack-NEXT: brasl %r14, extern_func + unsafe { + extern_func(); + } + 1 + // CHECK: br %r{{.*}} +} diff --git a/tests/codegen-llvm/packedstack.rs b/tests/codegen-llvm/packedstack.rs new file mode 100644 index 0000000000000..b8e849c31292f --- /dev/null +++ b/tests/codegen-llvm/packedstack.rs @@ -0,0 +1,16 @@ +//@ add-minicore +//@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-linux-gnu -Zpacked-stack +//@ needs-llvm-components: systemz +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[no_mangle] + +pub fn test_packedstack() { + // CHECK: @test_packedstack() unnamed_addr #0 +} +// CHECK: attributes #0 = { {{.*}}"packed-stack"{{.*}} } diff --git a/tests/ui/README.md b/tests/ui/README.md index 237cfb9c4f071..4c558186c68de 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1070,6 +1070,10 @@ Exercises operator overloading via [`std::ops`](https://doc.rust-lang.org/std/op See [`repr(packed)` | Nomicon](https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked-reprpackedn). +## `tests/ui/packedstack/` + +Tests different combinations that `-Zpacked-stack` will affect. + ## `tests/ui/panic-handler/` See [panic handler | Nomicon](https://doc.rust-lang.org/nomicon/panic-handler.html). diff --git a/tests/ui/packedstack/combination.need_softfloat.stderr b/tests/ui/packedstack/combination.need_softfloat.stderr new file mode 100644 index 0000000000000..99cc88554a2ae --- /dev/null +++ b/tests/ui/packedstack/combination.need_softfloat.stderr @@ -0,0 +1,10 @@ +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 `packedstack` and `backchain` attributes is incompatible with the default s390x target. 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/packedstack/combination.rs b/tests/ui/packedstack/combination.rs new file mode 100644 index 0000000000000..f50ffa88397ae --- /dev/null +++ b/tests/ui/packedstack/combination.rs @@ -0,0 +1,29 @@ +//@ revisions: wrong_arch only_packedstack need_softfloat with_softfloat +//@ compile-flags: -Zpacked-stack --crate-type=lib + +//@ [wrong_arch] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [wrong_arch] needs-llvm-components: x86 + +//@ [only_packedstack] compile-flags: --target=s390x-unknown-linux-gnu +//@ [only_packedstack] build-pass +//@ [only_packedstack] needs-llvm-components: systemz + +//@ [need_softfloat] compile-flags: -Ctarget-feature=+backchain --target=s390x-unknown-linux-gnu +//@ [need_softfloat] check-fail +//@ [need_softfloat] needs-llvm-components: systemz + +//@ [with_softfloat] compile-flags: -Ctarget-feature=+backchain +//@ [with_softfloat] compile-flags: --target=s390x-unknown-none-softfloat +//@ [with_softfloat] build-pass +//@ [with_softfloat] needs-llvm-components: systemz + +//@ ignore-backends: gcc + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +//[wrong_arch]~? ERROR `-Zpacked-stack` is only supported on s390x +//[need_softfloat]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` +//[need_softfloat]~? ERROR packedstack with backchain needs softfloat +//[with_softfloat]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` diff --git a/tests/ui/packedstack/combination.with_softfloat.stderr b/tests/ui/packedstack/combination.with_softfloat.stderr new file mode 100644 index 0000000000000..b8c06fc57a448 --- /dev/null +++ b/tests/ui/packedstack/combination.with_softfloat.stderr @@ -0,0 +1,6 @@ +warning: unstable feature specified for `-Ctarget-feature`: `backchain` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 1 warning emitted + diff --git a/tests/ui/packedstack/combination.wrong_arch.stderr b/tests/ui/packedstack/combination.wrong_arch.stderr new file mode 100644 index 0000000000000..aa178ad69c627 --- /dev/null +++ b/tests/ui/packedstack/combination.wrong_arch.stderr @@ -0,0 +1,4 @@ +error: `-Zpacked-stack` is only supported on s390x + +error: aborting due to 1 previous error +