diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index d51adb6e13b07..1acb0925fce98 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -3,16 +3,17 @@ use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSettin use rustc_hir::def_id::DefId; use rustc_hir::find_attr; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, TargetFeature, }; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet}; +use rustc_span::sym; use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{Arch, FramePointer, SanitizerSet, StackProbeType, StackProtector}; use smallvec::SmallVec; use crate::context::SimpleCx; -use crate::errors::SanitizerMemtagRequiresMte; +use crate::errors::{PackedStackBackchainNeedsSoftfloat, SanitizerMemtagRequiresMte}; use crate::llvm::AttributePlace::Function; use crate::llvm::{ self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects, Value, @@ -301,6 +302,36 @@ fn stackprotector_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll A Some(sspattr.create_attr(cx.llcx)) } +fn packed_stack_attr<'ll>( + cx: &SimpleCx<'ll>, + sess: &Session, + function_attributes: &Vec, +) -> Option<&'ll Attribute> { + if sess.target.arch != Arch::S390x { + return None; + } + if !sess.opts.unstable_opts.packed_stack { + return None; + } + + // 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.unstable_target_features.contains(&sym::backchain) + || function_attributes.iter().any(|feature| feature.name == sym::backchain); + let have_softfloat = sess.unstable_target_features.contains(&sym::soft_float) + || function_attributes.iter().any(|feature| feature.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; + } + + Some(llvm::CreateAttrString(cx.llcx, "packed-stack")) +} + 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) @@ -516,6 +547,9 @@ 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); + } to_add.extend(patchable_function_entry_attrs( cx, sess, diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 9fb406516f66a..818a0a37296f4 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -204,3 +204,10 @@ pub(crate) struct MismatchedDataLayout<'a> { pub(crate) struct FixedX18InvalidArch<'a> { pub arch: &'a str, } + +#[derive(Diagnostic)] +#[diag("`-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" +)] +pub(crate) struct PackedStackBackchainNeedsSoftfloat; diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index d1899de067b4f..295d9c3617778 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -530,3 +530,7 @@ pub(crate) struct UnexpectedBuiltinCfg { #[derive(Diagnostic)] #[diag("ThinLTO is not supported by the codegen backend, using fat LTO instead")] pub(crate) struct ThinLtoNotSupportedByBackend; + +#[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 fb1b3c8679481..1b74245a0f278 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2543,6 +2543,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 fece46dd9711d..c506276fd6ad3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1360,6 +1360,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } } + + 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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 738c9b975fd00..44d7d6144c0f2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -505,6 +505,7 @@ symbols! { avx512bw, avx512f, await_macro, + backchain, bang, begin_panic, bench, @@ -1917,6 +1918,7 @@ symbols! { slice_len_fn, slice_patterns, slicing_syntax, + soft_float: "soft-float", sparc, sparc64, sparc_target_feature, 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..11a01e60f8d40 --- /dev/null +++ b/tests/codegen-llvm/packedstack.rs @@ -0,0 +1,18 @@ +//@ add-minicore +//@ compile-flags: -Copt-level=3 --crate-type=lib --target=s390x-unknown-none-softfloat -Zpacked-stack +//@ needs-llvm-components: systemz +#![feature(s390x_target_feature)] +#![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/target-feature/packedstack-combinations.backchain_attr.stderr b/tests/ui/target-feature/packedstack-combinations.backchain_attr.stderr new file mode 100644 index 0000000000000..6270e43e93255 --- /dev/null +++ b/tests/ui/target-feature/packedstack-combinations.backchain_attr.stderr @@ -0,0 +1,6 @@ +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 new file mode 100644 index 0000000000000..6f4531945ee07 --- /dev/null +++ b/tests/ui/target-feature/packedstack-combinations.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 `-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 new file mode 100644 index 0000000000000..5dc0f6adf812e --- /dev/null +++ b/tests/ui/target-feature/packedstack-combinations.rs @@ -0,0 +1,44 @@ +//@ add-minicore +//@ revisions: wrong_arch only_packedstack backchain_attr backchain_cli with_softfloat +//@ compile-flags: -Zpacked-stack --crate-type=rlib +//@ ignore-backends: gcc + +//@ [wrong_arch] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [wrong_arch] should-fail +//@ [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 + +//@ [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] should-fail +//@ [backchain_cli] 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 + +#![feature(s390x_target_feature)] +#![crate_type = "rlib"] +#![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() { +} + +//[wrong_arch]~? ERROR `-Zpacked-stack` is only supported on s390x +//[backchain_cli]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` +//[backchain_cli]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature +//[backchain_attr]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature +//[with_softfloat]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` diff --git a/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr b/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr new file mode 100644 index 0000000000000..b8c06fc57a448 --- /dev/null +++ b/tests/ui/target-feature/packedstack-combinations.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/target-feature/packedstack-combinations.wrong_arch.stderr b/tests/ui/target-feature/packedstack-combinations.wrong_arch.stderr new file mode 100644 index 0000000000000..aa178ad69c627 --- /dev/null +++ b/tests/ui/target-feature/packedstack-combinations.wrong_arch.stderr @@ -0,0 +1,4 @@ +error: `-Zpacked-stack` is only supported on s390x + +error: aborting due to 1 previous error +