https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87733

--- Comment #12 from Rich Felker <bugdal at aerifal dot cx> ---
> You can work around it on older GCC by simply not using a register var
> for more than one asm operand, I think?

Nope. Making a syscall inherently requires binding specific registers for all
of the inputs/outputs, unless you want to spill everything to an explicit
structure in memory and load them all explicitly in the asm block. So it really
is a big deal.

In particular, all mips variants need an earlyclobber constraint for the output
register $2 because the old Linux kernel syscall contract was that, when
restartable syscalls were interrupted, the syscall number passed in through $2
was lost, and the kernel returned to $pc-8 and expected a userspace instruction
to reload $2 with the syscall number from an immediate or another register. If
the input to load into $2 were itself passed in $2 (possible without
earlyclobber), the reloading would be ineffective and restarting syscalls would
execute the wrong syscall.

The original mips port of musl had undocumented and seemingly useless "0"(r2)
input constraints that were suppressing this bug, using the input to bind the
register where the earlyclobber output failed to do so. After some recent
changes broke compatibility with older kernels requiring the above contract, I
manually reverted them (due to intervening conflicting diffs) and omitted the
seemingly useless constraint, and it broke horribly. Eventually I found this
bug searching the tracker. My plan for now is just to add back the "0"(r2)
constraint, but since r2 is uninitialized, it's not clear that having it as an
input constraint is even well-defined. Is this the best thing to do?

Reply via email to