[PATCH] ARM: Do not tail-call to an externally-defined function with weak linkage

Oliver Stannard oliver.stannard at arm.com
Thu Aug 14 08:45:07 PDT 2014


Externally-defined functions with weak linkage should not be
tail-called on ARM or AArch64, as the AAELF spec requires normal calls
to undefined weak functions to be replaced with a NOP or jump to the
next instruction. The behaviour of branch instructions in this
situation (as used for tail calls) is implementation-defined, so we
cannot rely on the linker replacing the tail call with a return.

http://reviews.llvm.org/D4906

Files:
  lib/Transforms/Scalar/TailRecursionElimination.cpp
  test/Transforms/TailCallElim/AArch64/lit.local.cfg
  test/Transforms/TailCallElim/AArch64/weak-linkage.ll
  test/Transforms/TailCallElim/ARM/lit.local.cfg
  test/Transforms/TailCallElim/ARM/weak-linkage.ll

Index: lib/Transforms/Scalar/TailRecursionElimination.cpp
===================================================================
--- lib/Transforms/Scalar/TailRecursionElimination.cpp
+++ lib/Transforms/Scalar/TailRecursionElimination.cpp
@@ -54,6 +54,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/CaptureTracking.h"
 #include "llvm/Analysis/CFG.h"
 #include "llvm/Analysis/InlineCost.h"
@@ -298,6 +299,20 @@
       if (!CI || CI->isTailCall())
         continue;
 
+      // Externally-defined functions with weak linkage should not be
+      // tail-called on ARM or AArch64, as the AAELF spec requires normal calls
+      // to undefined weak functions to be replaced with a NOP or jump to the
+      // next instruction. The behaviour of branch instructions in this
+      // situation (as used for tail calls) is implementation-defined, so we
+      // cannot rely on the linker replacing the tail call with a return.
+      GlobalValue *Callee = dyn_cast<GlobalValue>(CI->getCalledValue());
+      Triple T(F.getParent()->getTargetTriple());
+      if ((T.getArch() == Triple::arm || T.getArch() == Triple::armeb ||
+          T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb ||
+          T.getArch() == Triple::aarch64 || T.getArch() == Triple::aarch64_be)
+          && Callee && Callee->hasExternalWeakLinkage())
+        continue;
+
       if (CI->doesNotAccessMemory()) {
         // A call to a readnone function whose arguments are all things computed
         // outside this function can be marked tail. Even if you stored the
Index: test/Transforms/TailCallElim/AArch64/lit.local.cfg
===================================================================
--- /dev/null
+++ test/Transforms/TailCallElim/AArch64/lit.local.cfg
@@ -0,0 +1,3 @@
+if not 'AArch64' in config.root.targets:
+    config.unsupported = True
+
Index: test/Transforms/TailCallElim/AArch64/weak-linkage.ll
===================================================================
--- /dev/null
+++ test/Transforms/TailCallElim/AArch64/weak-linkage.ll
@@ -0,0 +1,10 @@
+; RUN: opt -mtriple=aarch64--none-eabi < %s -tailcallelim -S | FileCheck %s
+
+declare extern_weak void @weak_function()
+
+; Don't tail call to a weak symbol
+define void @func1() {
+; CHECK-NOT: tail call
+  call void @weak_function()
+  ret void
+}
Index: test/Transforms/TailCallElim/ARM/lit.local.cfg
===================================================================
--- /dev/null
+++ test/Transforms/TailCallElim/ARM/lit.local.cfg
@@ -0,0 +1,3 @@
+if not 'ARM' in config.root.targets:
+    config.unsupported = True
+
Index: test/Transforms/TailCallElim/ARM/weak-linkage.ll
===================================================================
--- /dev/null
+++ test/Transforms/TailCallElim/ARM/weak-linkage.ll
@@ -0,0 +1,10 @@
+; RUN: opt -mtriple=armv7a--none-eabi < %s -tailcallelim -S | FileCheck %s
+
+declare extern_weak void @weak_function()
+
+; Don't tail call to a weak symbol
+define void @func1() {
+; CHECK-NOT: tail call
+  call void @weak_function()
+  ret void
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4906.12509.patch
Type: text/x-patch
Size: 3158 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140814/c1aa9584/attachment.bin>


More information about the llvm-commits mailing list