Bug 32971 - Inline asm with offset addressing fails to compile in 4.0+ without -O
Summary: Inline asm with offset addressing fails to compile in 4.0+ without -O
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: inline-asm (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-08-03 04:47 UTC by Matthew Gregan [:kinetik]
Modified: 2007-08-03 12:17 UTC (History)
1 user (show)

See Also:
Host: i486-linux-gnu
Target: i486-linux-gnu
Build: i486-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments
testcase (181 bytes, text/plain)
2007-08-03 04:48 UTC, Matthew Gregan [:kinetik]
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Gregan [:kinetik] 2007-08-03 04:47:05 UTC
The following test case fails to compile without optimization with gcc 4.3.0 (20070503 (experimental)), 4.1.2 (20070502 (Red Hat 4.1.2-12)), and 4.0.4 (20060904 (prerelease) (Debian 4.0.3-7)), but succeeds with 3.3.6 (Debian 1:3.3.6-15) and 3.4.6 (Debian 3.4.6-5).  With optimization (-O and -O2), it compiles fine with all of the gcc versions mentioned above.

The failing configurations are generating invalid assembly and gas emits the following error:
/tmp/ccnbmIy1.s:12: Error: register value used as expression

Looking at the assembly emitted by gcc, the failing case looks like:
        lea (%edx)(%eax), %eax

..and with the working configurations, I get the expected code:
        lea 4(%eax), %eax

#include <stddef.h>

struct coord { int x; int y; };

int *
foo(struct coord * c)
{
  int * i;
  asm ("lea %1(%2), %0"
       : "=r" (i)
       : "m" (*(size_t *) offsetof(struct coord, y)),
	 "r" (c)
       : "memory");
  return i;
}
Comment 1 Matthew Gregan [:kinetik] 2007-08-03 04:48:21 UTC
Created attachment 14014 [details]
testcase
Comment 2 Matthew Gregan [:kinetik] 2007-08-03 04:51:33 UTC
Using a memory operand to pass the offset value is not ideal in the first place, but I'm not sure how else I can do it.  It looks like the "i" contraint (immediate value) is what I want, but the following code:

  asm ("lea %1(%2), %0"
       : "=r" (i)
       : "i" (offsetof(struct coord, y)),
         "r" (c)
       : "memory");

...generates the following assembly, which gas fails to assemble due to syntax errors:
        lea $4(%eax), %eax
Comment 3 Matthew Gregan [:kinetik] 2007-08-03 05:11:14 UTC
(In reply to comment #2)
>   asm ("lea %1(%2), %0"
>        : "=r" (i)
>        : "i" (offsetof(struct coord, y)),
>          "r" (c)
>        : "memory");

Bug #29357 suggests that I need to use %c1 rather than %1 here, and indeed this works and I believe this is the correct solution.

I'm don't know enough to know if the original reason I opened the bug is still valid (i.e. it's a regression), or if I'm just being bitten by behaviour changes when I'm abusing the meaning of the operand (I suspect the latter), so I'll leave the bug open for someone to review and confirm or close.
Comment 4 Andrew Pinski 2007-08-03 12:17:01 UTC
%m means it can represent it as memory access which means access it via a register, this is not a bug.