https://gcc.gnu.org/g:ffe3ead4a8ad704b557b0cfa4f823df647c65a0d

commit r17-5013-gffe3ead4a8ad704b557b0cfa4f823df647c65a0d
Author: Vineet Gupta <[email protected]>
Date:   Fri Oct 9 14:15:07 2026 +0530

    bpf: add -mcallx, enabled for CPU v1 and above
    
    Indirect calls were only generated with -mxbpf, and otherwise diagnosed
    as an error.  The `callx' instruction is however part of the BPF CPU v1
    ISA, and is accepted by the assembler for v1 without -mxbpf.  It is also
    emitted by LLVM for all CPU versions.
    
    Make it an ISA feature like the others: add -mcallx/-mno-callx, enabled
    by default for CPU v1 and above, i.e. always, along with the
    corresponding __BPF_FEATURE_CALLX macro.  -mno-callx restores the old
    behaviour of diagnosing indirect calls.
    
    This was the last user of TARGET_XBPF in the compiler; -mxbpf is now
    only passed on to the assembler.  Document it as such, which also drops
    the only effect its documentation listed, the saving and restoring of
    callee-saved registers, removed in r11-490-g98456a64b0b5.
    
    gcc/ChangeLog:
    
            * config/bpf/bpf.opt (mcallx): New option.
            * config/bpf/bpf.cc (bpf_option_override): Enable bpf_has_callx
            for CPU v1 and above.
            (bpf_output_call): Check bpf_has_callx instead of TARGET_XBPF.
            (bpf_small_register_classes_for_mode_p): Likewise.
            * config/bpf/bpf-c.cc (bpf_target_macros): Define
            __BPF_FEATURE_CALLX.
            * config/bpf/bpf.md (call_internal): Update comment.
            * doc/invoke.texi (eBPF Options): Document -mcallx.  Document
            that -mxbpf is only passed on to the assembler, and remove the
            stale note about callee-saved registers.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/bpf/diag-indcalls.c: Pass -mno-callx.
            * gcc.target/bpf/feature-macro-1.c: Pass -mcallx and check
            __BPF_FEATURE_CALLX.
            * gcc.target/bpf/feature-macro-3.c: New test.
            * gcc.target/bpf/feature-macro-4.c: New test.
            * gcc.target/bpf/indirect-call-1.c: New test.
            * gcc.target/bpf/indirect-call-2.c: New test.
    
    Signed-off-by: Vineet Gupta <[email protected]>

Diff:
---
 gcc/config/bpf/bpf-c.cc                        |  2 ++
 gcc/config/bpf/bpf.cc                          | 12 +++++++-----
 gcc/config/bpf/bpf.md                          |  2 +-
 gcc/config/bpf/bpf.opt                         |  4 ++++
 gcc/doc/invoke.texi                            | 27 ++++++++++++++++++--------
 gcc/testsuite/gcc.target/bpf/diag-indcalls.c   |  2 +-
 gcc/testsuite/gcc.target/bpf/feature-macro-1.c |  6 +++++-
 gcc/testsuite/gcc.target/bpf/feature-macro-3.c |  6 ++++++
 gcc/testsuite/gcc.target/bpf/feature-macro-4.c |  6 ++++++
 gcc/testsuite/gcc.target/bpf/indirect-call-1.c | 21 ++++++++++++++++++++
 gcc/testsuite/gcc.target/bpf/indirect-call-2.c | 22 +++++++++++++++++++++
 11 files changed, 94 insertions(+), 16 deletions(-)

diff --git a/gcc/config/bpf/bpf-c.cc b/gcc/config/bpf/bpf-c.cc
index d80c5fdf4f18..33b15f44daaf 100644
--- a/gcc/config/bpf/bpf-c.cc
+++ b/gcc/config/bpf/bpf-c.cc
@@ -76,6 +76,8 @@ bpf_target_macros (cpp_reader *pfile)
     builtin_define ("__BPF_FEATURE_SDIV_SMOD");
   if (bpf_has_smov)
     builtin_define ("__BPF_FEATURE_MOVSX");
+  if (bpf_has_callx)
+    builtin_define ("__BPF_FEATURE_CALLX");
 
   /* Other CPU features can only be enabled/disabled generically by
      selecting the corresponding CPU version.  */
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index b7227f1c135c..d63341022f4d 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -248,6 +248,9 @@ bpf_option_override (void)
   if (bpf_has_smov == -1)
     bpf_has_smov = (bpf_isa >= ISA_V4);
 
+  if (bpf_has_callx == -1)
+    bpf_has_callx = (bpf_isa >= ISA_V1);
+
   /* Disable -fstack-protector as it is not supported in BPF.  */
   if (flag_stack_protect)
     {
@@ -759,8 +762,7 @@ bpf_output_destructor (rtx symbol, int priority 
ATTRIBUTE_UNUSED)
    is an RTX denoting the address of the called function.
 
    The main purposes of this function are:
-   - To reject indirect CALL instructions, which are not supported by
-     eBPF, unless targeting xBPF.
+   - To reject indirect CALL instructions when disabled by -mno-callx.
    - To recognize calls to kernel helper functions and emit the
      corresponding CALL N instruction.
 
@@ -792,7 +794,7 @@ bpf_output_call (const char *templ, rtx *operands, int 
target_index)
        break;
       }
     default:
-      if (!TARGET_XBPF)
+      if (!bpf_has_callx)
        {
          error ("indirect call in function, which are not supported by eBPF");
          operands[target_index] = GEN_INT (0);
@@ -1317,11 +1319,11 @@ bpf_asm_named_section (const char *name, unsigned int 
flags,
 static bool
 bpf_small_register_classes_for_mode_p (machine_mode mode)
 {
-  if (TARGET_XBPF)
+  if (bpf_has_callx)
     return 1;
   else
     /* Avoid putting function addresses in registers, as calling these
-       is not supported in eBPF.  */
+       is not supported with -mno-callx.  */
     return (mode != FUNCTION_MODE);
 }
 
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index a577b494133f..15d0f95cf0d0 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -540,7 +540,7 @@
 })
 
 ;; Emit a direct call for a constant address (S), or an indirect call
-;; for a register (r), the latter only generated when targeting xBPF.
+;; for a register (r), the latter unless disabled by -mno-callx.
 ;; Indirect calls are spelled `callx rN' in the pseudo-C dialect but
 ;; `call %rN' in the normal one.
 (define_insn "call_internal"
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index 7d948119586f..70e2170a784c 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -75,6 +75,10 @@ msmov
 Target Var(bpf_has_smov) Init(-1)
 Enable signed move and memory load instructions.
 
+mcallx
+Target Var(bpf_has_callx) Init(-1)
+Enable indirect call instructions.
+
 mcpu=
 Target RejectNegative Joined Var(bpf_isa) Enum(bpf_isa) Init(ISA_V4)
 Select the eBPF ISA version to target in code generation.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 272ad0cb6f1b..66d80f17e740 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1089,7 +1089,7 @@ Objective-C and Objective-C++ Dialects}.
 @emph{eBPF Options} (@ref{eBPF Options})
 @gccoptlist{-mbig-endian  -mlittle-endian
 -mframe-limit=@var{bytes}  -mxbpf  -mco-re  -mjmpext  -mjmp32
--malu32  -mv3-atomics  -mbswap  -msdiv  -msmov  -mcpu=@var{version}
+-malu32  -mv3-atomics  -mbswap  -msdiv  -msmov  -mcallx  -mcpu=@var{version}
 -masm=@var{dialect}  -minline-memops-threshold=@var{bytes}
 -Wco-re}
 
@@ -26723,6 +26723,16 @@ CPU v4 and above.
 Enable or disable sign-extending move and memory load instructions.
 Enabled for CPU v4 and above.
 
+@opindex mcallx
+@opindex mno-callx
+@item -mcallx
+@itemx -mno-callx
+Enable or disable indirect call instructions, i.e.@: calls through a
+function pointer, which are emitted as @code{call %r@var{N}} in the
+@samp{normal} assembly dialect and as @code{callx r@var{N}} in the
+@samp{pseudoc} one.  With @option{-mno-callx} an indirect call is
+diagnosed as an error.  Enabled for CPU v1 and above.
+
 @opindex mcpu
 @item -mcpu=@var{version}
 This specifies which version of the eBPF ISA to target. Newer versions
@@ -26732,7 +26742,8 @@ Supported values for @var{version} are:
 
 @table @samp
 @item v1
-The first stable eBPF ISA with no special features or extensions.
+The first stable eBPF ISA.  Supports indirect calls, as in
+@option{-mcallx}.
 
 @item v2
 Supports the jump extensions, as in @option{-mjmpext}.
@@ -26765,12 +26776,12 @@ information for the BPF target (@option{-gbtf}).
 @opindex mxbpf
 @opindex mno-xbpf
 @item -mxbpf
-Generate code for an expanded version of BPF, which relaxes some of
-the restrictions imposed by the BPF architecture:
-@itemize @minus
-@item Save and restore callee-saved registers at function entry and
-exit, respectively.
-@end itemize
+Target xBPF, an expanded version of BPF which relaxes some of the
+restrictions imposed by the BPF architecture.  This option does not
+currently affect code generation: it is passed on to the assembler,
+where it selects the @samp{xbpf} ISA spec and thus enables the assembly
+of xBPF-only instructions.  Note that code using such instructions is
+not accepted by the kernel BPF verifier.
 
 @opindex masm=@var{dialect}
 @item -masm=@var{dialect}
diff --git a/gcc/testsuite/gcc.target/bpf/diag-indcalls.c 
b/gcc/testsuite/gcc.target/bpf/diag-indcalls.c
index 9263fcf7e1a3..e83b03fd9987 100644
--- a/gcc/testsuite/gcc.target/bpf/diag-indcalls.c
+++ b/gcc/testsuite/gcc.target/bpf/diag-indcalls.c
@@ -1,6 +1,6 @@
 /* Verify proper errors are generated for indirect function calls.  */
 /* { dg-do compile } */
-/* { dg-options "-O0" } */
+/* { dg-options "-O0 -mno-callx" } */
 
 void (*fnp) (void);
 
diff --git a/gcc/testsuite/gcc.target/bpf/feature-macro-1.c 
b/gcc/testsuite/gcc.target/bpf/feature-macro-1.c
index 5fa7d3f46a2a..dc099360038f 100644
--- a/gcc/testsuite/gcc.target/bpf/feature-macro-1.c
+++ b/gcc/testsuite/gcc.target/bpf/feature-macro-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mcpu=v1 -malu32 -mjmp32 -mjmpext -mbswap -msdiv -msmov" } */
+/* { dg-options "-mcpu=v1 -malu32 -mjmp32 -mjmpext -mbswap -msdiv -msmov 
-mcallx" } */
 
 #ifndef __BPF_FEATURE_ALU32
 #error __BPF_FEATURE_ALU32 undefined
@@ -21,6 +21,10 @@
 #error __BPF_FEATURE_MOVSX undefined
 #endif
 
+#ifndef __BPF_FEATURE_CALLX
+#error __BPF_FEATURE_CALLX undefined
+#endif
+
 #ifdef __BPF_FEATURE_LDSX
 #error __BPF_FEATURE_LDSX defined with -mcpu=v1
 #endif
diff --git a/gcc/testsuite/gcc.target/bpf/feature-macro-3.c 
b/gcc/testsuite/gcc.target/bpf/feature-macro-3.c
new file mode 100644
index 000000000000..bd63fac2e8c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/feature-macro-3.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v1" } */
+
+#ifndef __BPF_FEATURE_CALLX
+#error __BPF_FEATURE_CALLX undefined with -mcpu=v1
+#endif
diff --git a/gcc/testsuite/gcc.target/bpf/feature-macro-4.c 
b/gcc/testsuite/gcc.target/bpf/feature-macro-4.c
new file mode 100644
index 000000000000..b1254abe7d06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/feature-macro-4.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-callx" } */
+
+#ifdef __BPF_FEATURE_CALLX
+#error __BPF_FEATURE_CALLX defined with -mno-callx
+#endif
diff --git a/gcc/testsuite/gcc.target/bpf/indirect-call-1.c 
b/gcc/testsuite/gcc.target/bpf/indirect-call-1.c
new file mode 100644
index 000000000000..916f886043a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/indirect-call-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v1 -masm=normal" } */
+
+/* GCC should generate an indirect call instruction (call %REG) for
+   CPU v1 and above, without -mxbpf.  */
+
+void
+foo ()
+{
+  ;
+}
+
+void
+bar()
+{
+  void (*funp) () = &foo;
+
+  (*funp) ();
+}
+
+/* { dg-final { scan-assembler "call\t%r" } } */
diff --git a/gcc/testsuite/gcc.target/bpf/indirect-call-2.c 
b/gcc/testsuite/gcc.target/bpf/indirect-call-2.c
new file mode 100644
index 000000000000..9f3a5a6361b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/indirect-call-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v1 -masm=pseudoc" } */
+
+/* GCC should generate an indirect call instruction (callx REG) for
+   CPU v1 and above, without -mxbpf.  */
+
+void
+foo ()
+{
+  ;
+}
+
+void
+bar()
+{
+  void (*funp) () = &foo;
+
+  (*funp) ();
+}
+
+/* { dg-final { scan-assembler "callx\tr" } } */
+/* { dg-final { scan-assembler-not "call\tr" } } */

Reply via email to