BPF currently limits the number of registers used to pass arguments to
functions to five registers.  There is a check for this at function
expansion time.  However, if a function is guaranteed to be always
inlined (and its body never generated) by virtue of the always_inline
attribute, it can "receive" any number of arguments.

Tested in host x86_64-linux-gnu and target bpf-unknown-none.

gcc/ChangeLog

        * config/bpf/bpf.cc (bpf_function_arg_advance): Do not complain
        about too many arguments if function is always inlined.

gcc/testsuite/ChangeLog

        * gcc.target/bpf/diag-funargs-inline-1.c: New test.
        * gcc.target/bpf/diag-funargs.c: Adapt test.
---
 gcc/config/bpf/bpf.cc                         |  9 +++++++-
 .../gcc.target/bpf/diag-funargs-inline-1.c    | 21 +++++++++++++++++++
 gcc/testsuite/gcc.target/bpf/diag-funargs.c   |  8 ++++++-
 3 files changed, 36 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/diag-funargs-inline-1.c

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 33218b3a818..d27a971d0af 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -732,7 +732,14 @@ bpf_function_arg_advance (cumulative_args_t ca,
   unsigned num_words = CEIL (num_bytes, UNITS_PER_WORD);
 
   if (*cum <= 5 && *cum + num_words > 5)
-    error ("too many function arguments for eBPF");
+    {
+      /* Too many arguments for BPF.  However, if the function is
+         gonna be inline for sure, we let it pass.  Otherwise, issue
+         an error.  */
+      if (!lookup_attribute ("always_inline",
+                             DECL_ATTRIBUTES (cfun->decl)))
+        error ("too many function arguments for eBPF");
+    }
 
   *cum += num_words;
 }
diff --git a/gcc/testsuite/gcc.target/bpf/diag-funargs-inline-1.c 
b/gcc/testsuite/gcc.target/bpf/diag-funargs-inline-1.c
new file mode 100644
index 00000000000..e917ef1294e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/diag-funargs-inline-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+inline int __attribute__ ((always_inline))
+foo (int a1,
+     int a2,
+     int a3,
+     int a4,
+     int a5,
+     int a6)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6;
+}
+
+int
+bar (int i1, int i2, int i3, int i4, int i5)
+{
+  return foo (i1, i2, i3, i4, i5, 10);
+}
+
+/* { dg-final { scan-assembler-not "call\t.*" } } */
diff --git a/gcc/testsuite/gcc.target/bpf/diag-funargs.c 
b/gcc/testsuite/gcc.target/bpf/diag-funargs.c
index d4e9c0683f2..42b5f05b67c 100644
--- a/gcc/testsuite/gcc.target/bpf/diag-funargs.c
+++ b/gcc/testsuite/gcc.target/bpf/diag-funargs.c
@@ -11,5 +11,11 @@ foo (int a1,  /* { dg-error "too many function arguments" } 
*/
      int a5,
      int a6)
 {
-  return a6;
+  return a1 + a2 + a3 + a4 + a5 + a6;
+}
+
+int
+bar (int i1, int i2, int i3, int i4, int i5)
+{
+  return foo (i1, i2, i3, i4, i5, 10);
 }
-- 
2.30.2

Reply via email to