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'.

Reply via email to