https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128577
Bug ID: 128577
Summary: RISC-V backend never consults __attribute__((noplt)),
emitting PLT-mediated direct calls (call/tail sym@plt)
under -fPIC despite accepting the attribute without
warning
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Target: riscv64-*-*
Reproducer
----------
$ cat trigger.c
__attribute__((noplt)) int ext_noplt(int x);
int caller(int x) {
return ext_noplt(x) + 1;
}
int tail_caller(int x) {
return ext_noplt(x);
}
Compile command / flags:
$ riscv64-linux-gnu-gcc -O2 -fPIC -S trigger.c
Observed output (GCC 16.2.0):
caller:
...
call ext_noplt@plt
...
tail_caller:
...
tail ext_noplt@plt
(For comparison, x86_64 emits 'call *ext_noplt@GOTPCREL(%rip)' / 'jmp *...' and
aarch64 emits GOT-indirect adrp/ldr followed by blr/br.)
Expected behavior:
On riscv64, calls to functions annotated with __attribute__((noplt)) must
bypass
the PLT and load the target address from the GOT, just as -fno-plt already
does.
The noplt attribute is documented to make calls avoid the PLT in
position-independent code.
Root cause
----------
Source location: gcc/config/riscv/riscv.cc:1786 (riscv_classify_symbol),
gcc/config/riscv/riscv.cc:7746 (riscv_legitimize_call_address),
gcc/config/riscv/predicates.md (call_insn_operand).
The noplt attribute is registered globally for all targets in
gcc/c-family/c-attribs.cc and is accepted without warning on function
declarations. The RISC-V backend, however, only tests the global flag_plt
option and never calls lookup_attribute ("noplt", DECL_ATTRIBUTES (...))
anywhere
in config/riscv/. Under the default -fPIC (flag_plt == 1), calls to
[[gnu::noplt]] functions therefore still use PLT relocations
('call ext_noplt@plt' and 'tail ext_noplt@plt').
Impact:
Functions explicitly annotated with __attribute__((noplt)) to avoid lazy PLT
resolution or PLT stub indirection remain routed through the PLT on RISC-V.
Suggested Fix
-------------
In gcc/config/riscv/riscv.cc (riscv_classify_symbol and
riscv_legitimize_call_address) and gcc/config/riscv/predicates.md
(call_insn_operand), check
'SYMBOL_REF_DECL (op) && lookup_attribute ("noplt",
DECL_ATTRIBUTES (SYMBOL_REF_DECL (op)))' alongside '!flag_plt'.