Constraint for inline assembly with one register used for both an input variable and an output variable
Xi Ruoyao
xry111@xry111.site
Fri Jun 6 09:11:49 GMT 2025
On Fri, 2025-06-06 at 16:25 +0800, LIU Hao wrote:
> 在 2025-6-5 21:18, Segher Boessenkool 写道:
> > Hi!
> >
> > On Thu, Jun 05, 2025 at 02:14:24PM +0200, Georg-Johann Lay via Gcc-help wrote:
> > > Am 05.06.25 um 13:43 schrieb Xi Ruoyao via Gcc-help:
> > > > When we write syscall wrappers with inline assembly, we often need to
> > > > assign one register for both an input variable and an output variable.
> > > > Per https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html,
> > > > such an inline assembly can be written
> > > >
> > > > register int *p1 asm ("r0") = …;
> > > > register int *p2 asm ("r1") = …;
> > > > register int *result asm ("r0");
> > > > asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
> > > >
> > > > Note the use of constraint "0" for p1 which shares the same register as
> > > > result. But currently in the Linux kernel vDSO, they are actually
> > > > written like
> > > >
> > > > asm ("sysint" : "=r" (result) : "r" (p1), "r" (p2));
> > > >
> > > > So the question here: is using "r" for p1 valid or not? Do we need to
> > > > "fix" this everywhere for the vDSO?
> > >
> > > That code is perfectly fine, since the register numbers for p1 and
> > > result are the same "r0" at the point of the inline asm.
> >
> > Yup. Various compiler passes will not realise "result" is the same reg
> > as "p1", but that probably won't limit optimisation here.
>
> FWIW, maybe that's too much into the implementation details of GCC. Clang does not treat `p1` and
> `result` as referencing the same datum; a value that is written into one of them is not visible from the
> other, which can produce strange results like https://gcc.godbolt.org/z/nohrc9oxq
>
> So the suggestion below is much much better.
>
> (And this asm statement is likely a candidate for `volatile`.)
Yes, in the real kernel code they are volatile, and with volatile Clang
does the correct thing.
But Clang even refuse to compile it:
inline
int
rr_add_store(int* p)
{
register int t __asm__("eax");
register int old __asm__("eax") = *p;
__asm__ volatile ("nop" : "+r"(t) : "0"(old));
t += 100;
*p = t;
return old;
}
results in
<source>:7:41: error: invalid input constraint '0' in asm
7 | __asm__ volatile ("nop" : "+r"(t) : "0"(old));
| ^
--
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University
More information about the Gcc-help
mailing list