mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
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:
parent
830f3f205d
commit
d569561835
@ -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);
|
||||
|
@ -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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user