fix rdar://7590304, a miscompilation of objc apps on arm. The caller
authorChris Lattner <sabre@nondot.org>
Mon, 1 Feb 2010 18:11:34 +0000 (18:11 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 1 Feb 2010 18:11:34 +0000 (18:11 +0000)
of objc message send was getting marked arm_apcscc, but the prototype
isn't.  This is fine at runtime because objcmsgsend is implemented in
assembly.  Only turn a mismatched caller and callee into 'unreachable'
if the callee is a definition.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94986 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCalls.cpp
test/Transforms/InstCombine/call.ll

index 9c420c838739e0c7b0607d6c1513aee599608616..5de846e90cf361075f1b88fb5a37084dab450475 100644 (file)
@@ -692,10 +692,14 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
   Value *Callee = CS.getCalledValue();
 
   if (Function *CalleeF = dyn_cast<Function>(Callee))
-    if (CalleeF->getCallingConv() != CS.getCallingConv()) {
+    // If the call and callee calling conventions don't match, this call must
+    // be unreachable, as the call is undefined.
+    if (CalleeF->getCallingConv() != CS.getCallingConv() &&
+        // Only do this for calls to a function with a body.  A prototype may
+        // not actually end up matching the implementation's calling conv for a
+        // variety of reasons (e.g. it may be written in assembly).
+        !CalleeF->isDeclaration()) {
       Instruction *OldCall = CS.getInstruction();
-      // If the call and callee calling conventions don't match, this call must
-      // be unreachable, as the call is undefined.
       new StoreInst(ConstantInt::getTrue(Callee->getContext()),
                 UndefValue::get(Type::getInt1PtrTy(Callee->getContext())), 
                                   OldCall);
index 05c063d34be26ec404bcbc620dacec074899f3e7..dd65b969737d2716a988f3edb0ad773cc8c673c2 100644 (file)
@@ -75,7 +75,7 @@ define i32 @test5() {
 declare i32 @test6a(i32)
 
 define i32 @test6() {
-        %X = call i32 bitcast (i32 (i32)* @test6a to i32 ()*)( )                ; <i32> [#uses=1]
+        %X = call i32 bitcast (i32 (i32)* @test6a to i32 ()*)( )
         ret i32 %X
 ; CHECK: %X1 = call i32 @test6a(i32 0)
 ; CHECK: ret i32 %X1
@@ -96,3 +96,23 @@ define void @test7() {
 }
 
 
+; rdar://7590304
+declare void @test8a()
+
+define i8* @test8() {
+  invoke arm_apcscc void @test8a()
+          to label %invoke.cont unwind label %try.handler
+
+invoke.cont:                                      ; preds = %entry
+  unreachable
+
+try.handler:                                      ; preds = %entry
+  ret i8* null
+}
+
+; Don't turn this into "unreachable": the callee and caller don't agree in
+; calling conv, but the implementation of test8a may actually end up using the
+; right calling conv.
+; CHECK: @test8() {
+; CHECK-NEXT: invoke arm_apcscc void @test8a()
+