Re: Constraint for inline assembly with one register used for both an input variable and an output variable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx>
School of Aerospace Science and Technology, Xidian University




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux