diff mbox

[ARM] PR78255: wrong code generation for indirect sibling calls

Message ID 58248A11.5030302@arm.com
State New
Headers show

Commit Message

Andre Vieira (lists) Nov. 10, 2016, 2:54 p.m. UTC
Hi,

As reported in PR78255 there is currently an issue with indirect sibling
calls in ARM when the address of the sibling call is loaded into 'r3'
and that same register is chosen to align the stack.  See the report for
further information.

As I mentioned in the bugzilla ticket I am not sure this is the right
approach, though it works... Bootstrapped on ARM and no regressions.

Do you think this is OK? Another solution would be to make sure that
'arm_get_frame_offsets' recalculates offsets after we know that the call
is going to be indirect, i.e. after we know the address is going to be
loaded into a register, but I do not know what a sane way would be to
ensure this.

Regards,
Andre

gcc/ChangeLog
2016-11-10  Andre Vieira  <andre.simoesdiasvieira@arm.com>

        * config/arm/arm.md (sibcall_internal): Add 'use' to pattern.
        (sibcall_value_internal): Likewise.
        (sibcall_insn): Likewise.
        (sibcall_value_insn): Likewise.


gcc/testsuite/ChangeLog
2016-11-10  Andre Vieira  <andre.simoesdiasvieira@arm.com>

        * gcc.target/arm/pr78255.c: New.

Comments

Andre Vieira (lists) Nov. 11, 2016, 10:26 a.m. UTC | #1
On 10/11/16 14:54, Andre Vieira (lists) wrote:
> Hi,
> 
> As reported in PR78255 there is currently an issue with indirect sibling
> calls in ARM when the address of the sibling call is loaded into 'r3'
> and that same register is chosen to align the stack.  See the report for
> further information.
> 
> As I mentioned in the bugzilla ticket I am not sure this is the right
> approach, though it works... Bootstrapped on ARM and no regressions.
> 
> Do you think this is OK? Another solution would be to make sure that
> 'arm_get_frame_offsets' recalculates offsets after we know that the call
> is going to be indirect, i.e. after we know the address is going to be
> loaded into a register, but I do not know what a sane way would be to
> ensure this.
> 
> Regards,
> Andre
> 
> gcc/ChangeLog
> 2016-11-10  Andre Vieira  <andre.simoesdiasvieira@arm.com>
> 
>         * config/arm/arm.md (sibcall_internal): Add 'use' to pattern.
>         (sibcall_value_internal): Likewise.
>         (sibcall_insn): Likewise.
>         (sibcall_value_insn): Likewise.
> 
> 
> gcc/testsuite/ChangeLog
> 2016-11-10  Andre Vieira  <andre.simoesdiasvieira@arm.com>
> 
>         * gcc.target/arm/pr78255.c: New.
> 

I was looking at the bootstrap results of the wrong patch. This one
seems to break ARM bootstrap, I am looking into it...

Cheers,
Andre
diff mbox

Patch

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 8393f65bcf4c9c3e61b91e5adcd5f59ff7c6ec3f..ab28b15f3e4ebbaca2b8ec0523493b54cce8c306 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8192,7 +8192,8 @@ 
   [(parallel [(call (match_operand 0 "memory_operand" "")
 		    (match_operand 1 "general_operand" ""))
 	      (return)
-	      (use (match_operand 2 "" ""))])])
+	      (use (match_operand 2 "" ""))
+	      (use (match_dup 0))])])
 
 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
 (define_expand "sibcall"
@@ -8225,7 +8226,8 @@ 
 		   (call (match_operand 1 "memory_operand" "")
 			 (match_operand 2 "general_operand" "")))
 	      (return)
-	      (use (match_operand 3 "" ""))])])
+	      (use (match_operand 3 "" ""))
+	      (use (match_dup 1))])])
 
 (define_expand "sibcall_value"
   [(parallel [(set (match_operand 0 "" "")
@@ -8258,7 +8260,8 @@ 
  [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
 	(match_operand 1 "" ""))
   (return)
-  (use (match_operand 2 "" ""))]
+  (use (match_operand 2 "" ""))
+  (use (match_operand 3 "" ""))]
   "TARGET_32BIT && SIBLING_CALL_P (insn)"
   "*
   if (which_alternative == 1)
@@ -8279,7 +8282,8 @@ 
        (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
 	     (match_operand 2 "" "")))
   (return)
-  (use (match_operand 3 "" ""))]
+  (use (match_operand 3 "" ""))
+  (use (match_operand 4 "" ""))]
   "TARGET_32BIT && SIBLING_CALL_P (insn)"
   "*
   if (which_alternative == 1)
diff --git a/gcc/testsuite/gcc.target/arm/pr78255.c b/gcc/testsuite/gcc.target/arm/pr78255.c
new file mode 100644
index 0000000000000000000000000000000000000000..4901acea51466c0bac92d9cb90e52b00b450d88a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr78255.c
@@ -0,0 +1,57 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2" }  */
+
+#include <string.h>
+
+struct table_s
+    {
+    void (*fun0)
+        ( void );
+    void (*fun1)
+        ( void );
+    void (*fun2)
+        ( void );
+    void (*fun3)
+        ( void );
+    void (*fun4)
+        ( void );
+    void (*fun5)
+        ( void );
+    void (*fun6)
+        ( void );
+    void (*fun7)
+        ( void );
+    } table;
+
+void callback0(){__asm("mov r0, r0 \n\t");}
+void callback1(){__asm("mov r0, r0 \n\t");}
+void callback2(){__asm("mov r0, r0 \n\t");}
+void callback3(){__asm("mov r0, r0 \n\t");}
+void callback4(){__asm("mov r0, r0 \n\t");}
+
+void test (void) {
+    memset(&table, 0, sizeof table);
+
+    asm volatile ("" : : : "r3");
+
+    table.fun0 = callback0;
+    table.fun1 = callback1;
+    table.fun2 = callback2;
+    table.fun3 = callback3;
+    table.fun4 = callback4;
+    table.fun0();
+}
+
+void foo (void)
+{
+  __builtin_abort ();
+}
+
+int main (void)
+{
+  unsigned long p = (unsigned long) &foo;
+  asm volatile ("mov r3, %0" : : "r" (p));
+  test ();
+
+  return 0;
+}