Skip to content

Conversation

taylordotfish
Copy link
Contributor

Fixes #25209.

On PowerPC, some registers are both inputs to syscalls and clobbered by them. An example is r0, which initially contains the syscall number, but may be overwritten during execution of the syscall.

musl and glibc use a + (read-write) constraint to indicate this, which isn't supported in Zig. The current implementation of PowerPC syscalls in the Zig standard library instead lists these registers as both inputs and clobbers, but this results in the C backend generating code that is invalid for at least some C compilers, like GCC, which doesn't support the specifying the same register as both an input and a clobber:

$ clang test.c  # compiles successfully
$ gcc test.c
test.c: In function ‘os_linux_powerpc64_syscall0__3157’:
test.c:10:2: error: ‘asm’ specifier for variable ‘t3’ conflicts with ‘asm’ clobber list
   11 |  __asm volatile(" sc\n bns+ 1f\n neg 3, 3\n 1:": [ret]"=r"(t2): [number]"r"(t3): "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12");
      |  ^~~~~

This PR changes the PowerPC syscall functions to list such registers as inputs and outputs rather than inputs and clobbers; both Clang and GCC appear to be fine with this, and the CBE-generated code looks correct. Thanks to @jacobly0 who pointed out that it's possible to have multiple outputs; I had gotten the wrong idea from the documentation.

Fixes ziglang#25209.

On PowerPC, some registers are both inputs to syscalls and clobbered by
them. An example is r0, which initially contains the syscall number, but
may be overwritten during execution of the syscall.

musl and glibc use a `+` (read-write) constraint to indicate this, which
isn't supported in Zig. The current implementation of PowerPC syscalls
in the Zig standard library instead lists these registers as both inputs
and clobbers, but this results in the C backend generating code that is
invalid for at least some C compilers, like GCC, which doesn't support
the specifying the same register as both an input and a clobber.

This PR changes the PowerPC syscall functions to list such registers as
inputs and outputs rather than inputs and clobbers. Thanks to jacobly0
who pointed out that it's possible to have multiple outputs; I had
gotten the wrong idea from the documentation.
taylordotfish added a commit to taylordotfish/zig that referenced this pull request Sep 14, 2025
As far as I can tell, this has only been a problem with the C backend
(see ziglang#25229), which is specifically excluded from this inline asm call.
However, it's probably best to avoid it anyway and use output registers
instead. In this case, because we're ignoring r3, which is the real
"output" of the syscall, we can specify r0 as the sole `->` output
instead, avoiding the need for a separate variable.
@alexrp alexrp self-assigned this Sep 14, 2025
taylordotfish added a commit to taylordotfish/zig that referenced this pull request Sep 17, 2025
As far as I can tell, this has only been a problem with the C backend
(see ziglang#25229), which is specifically excluded from this inline asm call.
However, it's probably best to avoid it anyway and use output registers
instead. In this case, because we're ignoring r3, which is the real
"output" of the syscall, we can specify r0 as the sole `->` output
instead, avoiding the need for a separate variable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Failed to build zig on Linux PPC64LE architecture
2 participants