Open joshtriplett opened 3 years ago
It looks like this is https://bugs.llvm.org/show_bug.cgi?id=32530
A workaround is to use lea
instead of mov
.
That's true, but lea
has disadvantages as well: you can't lea
into a memory destination, whereas you can mov
into a memory destination as long as you have a constant source. (Though you can't move a 64-bit immediate directly to memory, which makes that a moot point for 64-bit addresses.)
I ran into a variant of this and just wanted to update on behavior.
(Note that C on godbolt you need to twiddle the 'link to binary' checkbox for it to actually assemble the asm)
With clang version 17.0.1 (godbolt):
mov rax, 2b
=> address of the label in raxmov rax, offset 2b
=> parse errorWith gcc 14.2 (godbolt):
mov rax, 2b
=> address of the label in raxmov rax, offset 2b
=> address of the label in raxWith Rust 1.80.0 (godbolt):
movq $2b, %rax
=> address of the label in raxmov rax, 2b
=> read memory at label offset (!!!)mov rax, offset 2b
=> parse errorSo I think at this point Clang matches gcc (at least in the case where it accepts), while Rust reading a label address is inexpressible.
(This came up in my win32 emulator here, in the code that manages 64-bit => 32-bit transitions, where I intentionally building a PIE-less binary because I need careful control over the memory layout of the first 4gb of address space.)
It looks like this is https://bugs.llvm.org/show_bug.cgi?id=32530
BTW, this bug is fixed upstream. This bug was about the offset
syntax in general, which appears to now be accepted by Rust:
"mov rax, {x}", // value of x
"mov rax, offset {x}", // address of x
However it appears local labels somehow behave differently.
In Intel-syntax assembly, to refer to the address of a symbol rather than the memory pointed to by that symbol, you have to write
offset symbol
rather than justsymbol
. For instance,mov rax, 1f
is equivalent tomov rax, qword ptr 1f
and moves the memory pointed to by1f
intorax
, whilemov rax, offset 1f
moves the address of1f
intorax
.GCC and GAS accept this syntax. However, clang and Rust do not.
(The examples below use position-dependent addressing for simplicity. Production code should use position-independent addressing.)