https://gcc.gnu.org/g:9e15bb5fc2efd1514d597866af1ca39fe0d19de8

commit r17-5012-g9e15bb5fc2efd1514d597866af1ca39fe0d19de8
Author: Vineet Gupta <[email protected]>
Date:   Fri Oct 9 14:14:52 2026 +0530

    bpf: spell xBPF indirect calls `callx' in the pseudo-C dialect
    
    An indirect call is spelled `callx rN' in the pseudo-C dialect however
    the call patterns emitted a single `call\t%N' template for both dialects,
    so a function pointer call built with -mxbpf could not be assembled
    because Pseudo-C is the default:
    
      $ bpf-unknown-none-gcc -mxbpf -O2 -c callx.c
      Error: unexpected register name `r0' in instruction `call r0'
    
    The only existing test for this, xbpf-indirect-call-1.c, passes
    -masm=normal and so did not catch it.
    
    A direct call is spelled `call' in both dialects, so the template cannot
    simply be turned into an alternation.  Instead split the call target
    constraint, which already distinguishes a constant call address (S) from
    a register, into two alternatives and give each its own template.
    
    gcc/ChangeLog:
    
            * config/bpf/bpf.md (call_internal): Split the call target
            constraint into separate alternatives for a constant address and
            for a register, and use the pseudo-C spelling `callx' for the
            latter.
            (call_value_internal): Likewise.
            * config/bpf/bpf.cc (bpf_output_call): Update comment.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/bpf/xbpf-indirect-call-2.c: New test.
    
    Signed-off-by: Vineet Gupta <[email protected]>

Diff:
---
 gcc/config/bpf/bpf.cc                              |  2 +-
 gcc/config/bpf/bpf.md                              | 16 +++++++++++----
 .../gcc.target/bpf/xbpf-indirect-call-2.c          | 23 ++++++++++++++++++++++
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 6bd714d50534..b7227f1c135c 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -760,7 +760,7 @@ bpf_output_destructor (rtx symbol, int priority 
ATTRIBUTE_UNUSED)
 
    The main purposes of this function are:
    - To reject indirect CALL instructions, which are not supported by
-     eBPF.
+     eBPF, unless targeting xBPF.
    - To recognize calls to kernel helper functions and emit the
      corresponding CALL N instruction.
 
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index a2bceb8998d7..a577b494133f 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -539,13 +539,19 @@
   DONE;
 })
 
+;; Emit a direct call for a constant address (S), or an indirect call
+;; for a register (r), the latter only generated when targeting xBPF.
+;; Indirect calls are spelled `callx rN' in the pseudo-C dialect but
+;; `call %rN' in the normal one.
 (define_insn "call_internal"
-  [(call (mem:DI (match_operand:DI 0 "call_operand" "Sr"))
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "S,r"))
          (match_operand:SI 1 "general_operand" ""))]
   ;; operands[2] is next_arg_register
   ;; operands[3] is struct_value_size_rtx.
   ""
-  { return bpf_output_call ("call\t%0", operands, 0); }
+  "@
+   *return bpf_output_call (\"call\t%0\", operands, 0);
+   *return bpf_output_call (\"{call\t%0|callx\t%0}\", operands, 0);"
   [(set_attr "type" "jmp")])
 
 (define_expand "call_value"
@@ -563,12 +569,14 @@
 
 (define_insn "call_value_internal"
   [(set (match_operand 0 "register_operand" "")
-       (call (mem:DI (match_operand:DI 1 "call_operand" "Sr"))
+       (call (mem:DI (match_operand:DI 1 "call_operand" "S,r"))
              (match_operand:SI 2 "general_operand" "")))]
   ;; operands[3] is next_arg_register
   ;; operands[4] is struct_value_size_rtx.
   ""
-  { return bpf_output_call ("call\t%1", operands, 1); }
+  "@
+   *return bpf_output_call (\"call\t%1\", operands, 1);
+   *return bpf_output_call (\"{call\t%1|callx\t%1}\", operands, 1);"
   [(set_attr "type" "jmp")])
 
 (define_insn "sibcall"
diff --git a/gcc/testsuite/gcc.target/bpf/xbpf-indirect-call-2.c 
b/gcc/testsuite/gcc.target/bpf/xbpf-indirect-call-2.c
new file mode 100644
index 000000000000..8e64eca4aa6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/xbpf-indirect-call-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mxbpf -masm=pseudoc" } */
+
+/* GCC should generate an indirect call instruction (callx REG) when
+   targeting xBPF in the pseudo-C assembly dialect.  The normal dialect
+   spelling (call %REG) is not accepted by the assembler in pseudo-C.  */
+
+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