An raw symbolic operand is useful in inline asm (e.g. in C++ to get the mangled name, or in C to let the compiler do some asm checking). In aarch64 and riscv, there is a documented (supported) approach. documented on https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints extern int var; void *addr(void) { return &var; } void addr_via_asm(void) { asm (".pushsection .xxx,\"aw\"; .dc.a %0; .popsection" :: "S"(addr)); // supported on aarch64 and riscv asm (".pushsection .xxx,\"aw\"; .dc.a %0; .popsection" :: "S"(&var)); // supported on aarch64 } On x86, it is unclear which should be preferred. It seems that the operand modifier 'p' can be used for a function, but not a variable. asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "m"(addr));
Isn't the i constraint the one you want to be portable: ‘i’ An immediate integer operand (one with constant value) is allowed. This includes symbolic constants whose values will be known only at assembly time or later.
(In reply to Andrew Pinski from comment #1) > Isn't the i constraint the one you want to be portable: > > ‘i’ > An immediate integer operand (one with constant value) is allowed. This > includes symbolic constants whose values will be known only at assembly time > or later. This is from https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html#Simple-Constraints
Note integer here does allow for pointers as that is still an integer value internally.
constraint "i" + "%p0"? asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "i"(addr)); // supported on aarch64 and riscv asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "i"(&var)); // supported on aarch64
(In reply to Hongtao.liu from comment #4) > constraint "i" + "%p0"? > > asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "i"(addr)); // > supported on aarch64 and riscv > asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "i"(&var)); // > supported on aarch64 constraint "i" + "%p0" does not work with -mcmodel=large: a.c:11:3: warning: ‘asm’ operand 0 probably does not match constraints 11 | asm volatile(".quad %p0" :: "i"(foo)); | ^~~ a.c:11:3: error: impossible constraint in ‘asm’ On aarch64, `asm volatile(".quad %0" :: "S"(foo));` works with -mcmodel=large -fno-pic (note: PIC large code model has not been implemented).
(In reply to Hongtao.liu from comment #4) > constraint "i" + "%p0"? > > asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "i"(addr)); // > supported on aarch64 and riscv > asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "i"(&var)); // > supported on aarch64 It looks like %p0 + "i" doesn't work with -fpie or -fpic... void k(); void foo() { asm("call %p0" :: "i"(k)); }
Strangely, the following works if compiled with optimizations enabled, -O1 and above, but not with -O0, when optimizations are disabled [[gnu::extended(; [dispatcher] "i" (static_cast<void (*) () noexcept>([] () noexcept -> void {})); ; start)]] asm (R"( .endif .rva %l[start], 1f, %c[dispatcher], 2f .seh_code )"); With -O0 the error is exceptions.cpp: In function 'void exceptions()': exceptions.cpp:59:5: warning: 'asm' operand 0 probably does not match constraints 59 | asm (R"( | ^~~ exceptions.cpp:59:5: error: impossible constraint in 'asm' With -O1 and above, %c[dispatcher] yields: .rva .L2, 1f, _ZZL10exceptionsvENUlPVK19_EXCEPTION_POINTERSPVKvE0_4_FUNES1_S3_, 2f
I've encountered another use case related to metadata sections (establish an artificial reference for linker garbage collection purposes) namespace ns { extern int var; } // defined in another translation unit void reference() { // if this is retained, ensure var is pulled in asm (".reloc ., BFD_RELOC_NONE, %0" :: "S"(&ns::var)); } Created https://gcc.gnu.org/pipermail/gcc-patches/2024-January/642580.html ([PATCH] i386: Add "z" constraint for symbolic address/label reference [PR105576])
*** Bug 113675 has been marked as a duplicate of this bug. ***
The master branch has been updated by H.J. Lu <hjl@gcc.gnu.org>: https://gcc.gnu.org/g:d7250100381b817114447d91fff4748526d4fb21 commit r14-8637-gd7250100381b817114447d91fff4748526d4fb21 Author: Fangrui Song <maskray@google.com> Date: Thu Jan 11 10:24:25 2024 -0800 i386: Add "Ws" constraint for symbolic address/label reference [PR105576] Printing the raw symbol is useful in inline asm (e.g. in C++ to get the mangled name). Similar constraints are available in other targets (e.g. "S" for aarch64/riscv, "Cs" for m68k). There isn't a good way for x86 yet, e.g. "i" doesn't work for PIC/-mcmodel=large. This patch adds "Ws". Here are possible use cases: ``` namespace ns { extern int var; } asm (".pushsection .xxx,\"aw\"; .dc.a %0; .popsection" :: "Ws"(&var)); asm (".reloc ., BFD_RELOC_NONE, %0" :: "Ws"(&var)); ``` gcc/ChangeLog: PR target/105576 * config/i386/constraints.md: Define constraint "Ws". * doc/md.texi: Document it. gcc/testsuite/ChangeLog: PR target/105576 * gcc.target/i386/asm-raw-symbol.c: New testcase.
Thanks to HJ for landing the GCC patch (milestone: 15?) for me. Note that I made a typo in the commit message. "Ws" should typically be used with the modifier 'p' ``` namespace ns { extern int var; } asm (".pushsection .xxx,\"aw\"; .dc.a %p0; .popsection" :: "Ws"(&var)); asm (".reloc ., BFD_RELOC_NONE, %p0" :: "Ws"(&var)); ``` The upcoming Clang 18 release will also support "Ws". For software utilizing this feature, for aarch64 and riscv, use the constraint "S".
(In reply to Fangrui Song from comment #11) > Thanks to HJ for landing the GCC patch (milestone: 15?) for me. It made into GCC 14.
*** Bug 115179 has been marked as a duplicate of this bug. ***
> Is there a way to capture a method address in inline asm that works in > -fPIC mode? Specifically I want to capture the address of a static > method that's in a class that's local to a function. I'm able to do it > in non-PIC mode but not PIC mode. I have a write up how to support raw symbol names for different architectures https://maskray.me/blog/2024-01-30-raw-symbol-names-in-inline-assembly Summary: AArch32: "US" (for symbol reference without an offset) AArch64: "S" x86: "Ws", GCC 14+, Clang 18+ MIPS/PowerPC/RISC-V: "s" I hope that newer ports all define LEGITIMATE_PIC_OPERAND_P so that "s" can be used.