Rollup merge of #152432 - fneddy:s390x_packed_stack_attribute, r=nikic

add rustc option -Zpacked-stack

this enables `-Zpacked-stack` just as `-mpacked-stack` in clang and gcc. packed-stack is needed on s390x for kernel development.

For reference: rust-lang/rust#151154 and rust-lang/rust#150766

look at @uweigand s post for full explanation of what this does. Here a wrap-up:

https://github.com/rust-lang/rust/pull/150766#issuecomment-3729074303
> [...]
> packed-stack [...] modifies how the compiler-generated function prolog/epilog code makes use of the 160 byte register save area provided by a caller to the callee [...]  this variant is not actually incompatible with the ABI - packed-stack and regular functions can freely call each other without ABI issues.
> [...]
> combination of -mpacked-stack and -mbackchain [...]  the location in the stack frame where the backchain link ought to be stored is not available. [...] is not supported at all with the default ABI
> [...]
> However, in the special case of also using soft-float, our (implied) soft-float ABI provides a different location for the backchain that is compatible with -mpacked-stack, so that combination should be supported
> [...]
This commit is contained in:
Jonathan Brouwer
2026-03-31 15:27:18 +02:00
committed by GitHub
13 changed files with 182 additions and 2 deletions
+36 -2
View File
@@ -3,16 +3,17 @@
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,
@@ -302,6 +303,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<TargetFeature>,
) -> 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)
@@ -517,6 +548,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,
@@ -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;
+4
View File
@@ -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;
+2
View File
@@ -2557,6 +2557,8 @@ pub(crate) fn parse_assert_incr_state(
"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],
+6
View File
@@ -1363,6 +1363,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.
+2
View File
@@ -505,6 +505,7 @@
avx512bw,
avx512f,
await_macro,
backchain,
bang,
begin_panic,
bench,
@@ -1919,6 +1920,7 @@
slice_len_fn,
slice_patterns,
slicing_syntax,
soft_float: "soft-float",
sparc,
sparc64,
sparc_target_feature,
@@ -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{{.*}}
}
+18
View File
@@ -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"{{.*}} }
@@ -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
@@ -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
@@ -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`
@@ -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
@@ -0,0 +1,4 @@
error: `-Zpacked-stack` is only supported on s390x
error: aborting due to 1 previous error