The ARM bare-metal configuration of the EABI specifies that an
unresolved weak direct call becomes a NOP rather than faulting; but this
is only supported for the BL instruction.  GCC mishandled this in some
cases by trying to convert such a call into a tail-call, but B
instructions are not covered by the requirement above, which means that
the optimization is unsafe.

Fixed thus:

2011-12-21  Richard Earnshaw  <rearn...@arm.com>

        PR target/51643
        * arm.c (arm_function_ok_for_sibcall): Don't try to tailcall a
        weak function on bare-metal EABI targets.

2011-12-21  Richard Earnshaw  <rearn...@arm.com>

        PR target/51643
        * gcc.target/arm/sibcall-2.c: New test.
Index: testsuite/gcc.target/arm/sibcall-2.c
===================================================================
--- testsuite/gcc.target/arm/sibcall-2.c        (revision 0)
+++ testsuite/gcc.target/arm/sibcall-2.c        (revision 0)
@@ -0,0 +1,12 @@
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=aapcs" } */
+
+
+extern void __attribute__((weak)) wfunc(void);
+void main(void)
+{
+  wfunc();  /* Must not tail-call.  */
+}
+
+/* { dg-final { scan-assembler-not "b\[\\t \]+wfunc" } } */
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c    (revision 182620)
+++ config/arm/arm.c    (working copy)
@@ -5250,6 +5250,14 @@ arm_function_ok_for_sibcall (tree decl, 
   if (IS_STACKALIGN (func_type))
     return false;
 
+  /* The AAPCS says that, on bare-metal, calls to unresolved weak
+     references should become a NOP.  Don't convert such calls into
+     sibling calls.  */
+  if (TARGET_AAPCS_BASED
+      && arm_abi == ARM_ABI_AAPCS
+      && lookup_attribute ("weak", DECL_ATTRIBUTES (decl)))
+    return false;
+
   /* Everything else is ok.  */
   return true;
 }

Reply via email to