fix rdar://7590304, a miscompilation of objc apps on arm. The caller

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
This commit is contained in:
Chris Lattner 2010-02-01 18:11:34 +00:00
parent 830f3f205d
commit d569561835
2 changed files with 28 additions and 4 deletions

View 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);

View 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()