Skip to content

s390x assembly does not use Rust's z10 CPU baseline #154

Description

@watany-dev

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions