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;
}