GCC's aarch64 port, from the beginning (2012), supports the constraint "S" to reference a symbol or label. This is nice, as you can create an artificial reference for linker garbage collection, defining sections to hold symbol addresses, or even enabling more creative applications.
1 | namespace ns { extern int a[4]; } |
Clang 7 also implemented "S".
Using the generic r
or m
constraint in such
cases would instruct GCC to generate instructions to compute the
address, which can be wasteful if the materialized address isn't
actually needed.
1 |
|
C++ templates can make this easier to use.
1 | template <class T, T &x> |
RISC-V
GCC's RISC-V port, from the beginning (2017), supports the constraint "S" for a similar purpose as well. However, the operand cannot be a preemptible symbol (non-local symbol in GCC's term). I have just filed [PATCH] RISC-V: Allow constraint "S" even if the symbol does not bind locally to relax the condition.
x86
Unfortunately, there had been no suitable constraint for x86 for a long time. We can use the constraint "i" with the modifier "p" to print raw symbol name without syntax-specific prefixes, but it does not work when:
-mcmodel=large
is used- or the symbol is preemptible (similar to RISC-V's "S" problem)
1 | void foo() { |
I filed the feature request for a new constraint in May 2022 and eventually went ahead and implement it by myself. The patch landed today, catching up the GCC 14 release. I have also implemented "Ws" for Clang 18.1.
BTW, you can also the modifier "c".
Require a constant operand and print the constant expression with no punctuation.
I think having such a long list of modifiers is unfortunate.
Applications
Linux kernel's config JUMP_LABEL
is a noticeable user of
this raw symbol name feature. Many ports just use the constraint "i",
which is kinda abuse.
1 | // gcc/common.md |
That said, in the non-PIC mode, "i" does works with a constant, symbol reference, or label reference. In the PIC mode, "i" on a symbol reference is rejected by certain GCC ports (e.g. aarch64). I went ahead and sent an arm64 patch:)