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; }
Created attachment 14014 [details] testcase
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
(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.
%m means it can represent it as memory access which means access it via a register, this is not a bug.