When building psm for s390x-unknown-linux-gnu, the s390x assembly is compiled separately through the cc crate, but the target's CPU baseline is not passed to the assembler.
Rust's s390x-unknown-linux-gnu target explicitly uses z10 as its baseline:
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
However, psm currently selects src/arch/zseries_linux.s for s390x without passing an equivalent -march=z10 option to the assembler.
This can cause the assembly to fail depending on the assembler's default machine level.
Root Cause
psm correctly selects the s390x assembly in build.rs:
("s390x", _, _, _) => Some(("src/arch/zseries_linux.s", true)),
The assembly is then built separately using cc::Build.
Although Rust compiles normal Rust code for the z10 baseline, that setting is not automatically propagated to the external assembler invocation used by cc.
As a result, instructions used by zseries_linux.s, such as lay, may be rejected if the assembler defaults to an older architecture level.
Previous report
This appears to be the same underlying problem previously reported in #79, where cross-compiling psm for s390x-unknown-linux-gnu failed with:
src/arch/zseries_linux.s:49: Error: Unrecognized opcode: `lay'
src/arch/zseries_linux.s:63: Error: operand out of range (...)
src/arch/zseries_linux.s:64: Error: Unrecognized opcode: `lay'
That build log also shows that none of the target-specific CFLAGS were set:
CFLAGS_s390x_unknown_linux_gnu = None
TARGET_CFLAGS = None
CFLAGS = None
#79 is now closed, but I couldn't find a corresponding change that sets the s390x machine level, and the current build.rs still does not pass an -march option for this target.
Downstream workaround
Ruff recently hit this when building its s390x release artifacts through stacker / psm.
astral-sh/ruff#27776 ("Fix s390x stacker assembly in release builds") works around the problem by explicitly setting:
CFLAGS_s390x_unknown_linux_gnu=-march=z10
The PR describes the change as passing the s390x architecture flag to release builds so that stacker builds successfully.
This suggests that explicitly selecting the z10 machine level fixes the existing psm assembly without requiring any changes to zseries_linux.s.
The workaround currently has to be applied by downstream projects even though z10 is already the baseline of Rust's s390x-unknown-linux-gnu target.
Related issues / PRs
The last three are not s390x-specific, but they seem relevant to the broader question of whether target-specific assembler configuration should be handled in build.rs or avoided by moving assembly into Rust.
When building
psmfors390x-unknown-linux-gnu, the s390x assembly is compiled separately through thecccrate, but the target's CPU baseline is not passed to the assembler.Rust's
s390x-unknown-linux-gnutarget explicitly uses z10 as its baseline:However,
psmcurrently selectssrc/arch/zseries_linux.sfor s390x without passing an equivalent-march=z10option to the assembler.This can cause the assembly to fail depending on the assembler's default machine level.
Root Cause
psmcorrectly selects the s390x assembly inbuild.rs:The assembly is then built separately using
cc::Build.Although Rust compiles normal Rust code for the z10 baseline, that setting is not automatically propagated to the external assembler invocation used by
cc.As a result, instructions used by
zseries_linux.s, such aslay, may be rejected if the assembler defaults to an older architecture level.Previous report
This appears to be the same underlying problem previously reported in #79, where cross-compiling
psmfors390x-unknown-linux-gnufailed with:That build log also shows that none of the target-specific CFLAGS were set:
#79 is now closed, but I couldn't find a corresponding change that sets the s390x machine level, and the current
build.rsstill does not pass an-marchoption for this target.Downstream workaround
Ruff recently hit this when building its s390x release artifacts through
stacker/psm.astral-sh/ruff#27776("Fix s390x stacker assembly in release builds") works around the problem by explicitly setting:The PR describes the change as passing the s390x architecture flag to release builds so that
stackerbuilds successfully.This suggests that explicitly selecting the z10 machine level fixes the existing
psmassembly without requiring any changes tozseries_linux.s.The workaround currently has to be applied by downstream projects even though z10 is already the baseline of Rust's
s390x-unknown-linux-gnutarget.Related issues / PRs
psmfails to cross-compile to s390x withlayreported as an unrecognized opcode. This appears to be the same failure mode.astral-sh/ruff#27776— Direct downstream workaround: passesCFLAGS_s390x_unknown_linux_gnu=-march=z10so thatstacker/psmbuilds successfully for Ruff's s390x releases.psmwhere an external assembly file does not receive the target-specific build context it needs. The architecture is different (aarch64-pc-windows-msvc), but the issue similarly comes from howbuild.rsconfigures separately assembled code.The last three are not s390x-specific, but they seem relevant to the broader question of whether target-specific assembler configuration should be handled in
build.rsor avoided by moving assembly into Rust.