[Bug middle-end/46164] New: Local variables in specified registers don't work correctly with inline asm operands

siarhei.siamashka at gmail dot com gcc-bugzilla@gcc.gnu.org
Mon Oct 25 10:13:00 GMT 2010


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46164

           Summary: Local variables in specified registers don't work
                    correctly with inline asm operands
           Product: gcc
           Version: 4.5.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: siarhei.siamashka@gmail.com


When testing with gcc 4.5.1

==== ARM ====

$ cat test.c

int f(int a)
{
  register int result asm("r0");
  asm (
    "add    r0, %[a], #123\n"
    : [result] "=&r" (result)
    : [a]      "r"   (a)
  );
  return result;
}

$ gcc -O2 -c test.c
$ objdump -d test.o

00000000 <f>:
   0:   e280007b        add     r0, r0, #123    ; 0x7b
   4:   e1a00003        mov     r0, r3
   8:   e12fff1e        bx      lr

Here the local variable 'result' gets assigned to register r3 instead of r0
causing all kind of problems.

==== x86-64 ====

$ cat test.c

int f(int a)
{
  register int result asm("edi");
  asm (
    "lea    0x7b(%[a]), %%edi\n"
    : [result] "=&r" (result)
    : [a]      "r"   (a)
  );
  return result;
}

$ gcc -O2 -c test.c
$ objdump -d test.o

0000000000000000 <f>:
   0:   67 8d 7f 7b             addr32 lea 0x7b(%edi),%edi
   4:   c3                      retq

=================================

And some final bits.

http://gcc.gnu.org/onlinedocs/gcc/Local-Reg-Vars.html#Local-Reg-Vars
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

The documantation is a bit confusing, but it gives at least one example of
assigining variables to specified registers:

"Sometimes you need to make an asm operand be a specific register, but there's
no matching constraint letter for that register by itself. To force the operand
into that register, use a local variable for the operand and specify the
register in the variable declaration. See Explicit Reg Vars. Then for the asm
operand, use any register constraint letter that matches the register:

     register int *p1 asm ("r0") = ...;
     register int *p2 asm ("r1") = ...;
     register int *result asm ("r0");
     asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));"

Let's try to use something like that with x86-64:

/********************/
void abort();

int __attribute__((noinline)) f(int a)
{
  register int p1 asm ("edi");
  register int result asm ("edi");
  asm (
    "mov %2, %0\n"
    "add %2, %0\n"
    "add %2, %0\n"
    : "=r" (result) : "0"  (p1), "r" (a));
  return result;
}

int main()
{
    if (f(1) != 3)
        abort();
}

/********************/

This testcase fails.

So is it a bug in gcc? Or the documentation is wrong? Or I'm missing something?



More information about the Gcc-bugs mailing list