mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Use the new ObjC retain/release intrinsics in IRGen.
This commit is contained in:
@@ -1163,17 +1163,6 @@ FUNCTION(InstantiateObjCClass, swift_instantiateObjCClass, C_CC,
|
||||
ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCAllocWithZone, objc_allocWithZone, C_CC,
|
||||
RETURNS(ObjCPtrTy), ARGS(ObjCClassPtrTy), ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCRetain, objc_retain, C_CC,
|
||||
RETURNS(ObjCPtrTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCRelease, objc_release, C_CC,
|
||||
RETURNS(VoidTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCAutorelease, objc_autorelease, C_CC,
|
||||
RETURNS(ObjCPtrTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCRetainAutoreleasedReturnValue,
|
||||
objc_retainAutoreleasedReturnValue, C_CC,
|
||||
RETURNS(Int8PtrTy), ARGS(Int8PtrTy), ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCAutoreleaseReturnValue, objc_autoreleaseReturnValue, C_CC,
|
||||
RETURNS(ObjCPtrTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
|
||||
FUNCTION(ObjCMsgSend, objc_msgSend, C_CC,
|
||||
RETURNS(VoidTy), NO_ARGS, NO_ATTRS)
|
||||
FUNCTION(ObjCMsgSendStret, objc_msgSend_stret, C_CC,
|
||||
|
||||
@@ -57,42 +57,36 @@
|
||||
using namespace swift;
|
||||
using namespace irgen;
|
||||
|
||||
void IRGenFunction::emitObjCStrongRelease(llvm::Value *value) {
|
||||
// Get an appropriately-cast function pointer.
|
||||
auto fn = IGM.getObjCReleaseFn();
|
||||
auto cc = IGM.C_CC;
|
||||
if (auto fun = dyn_cast<llvm::Function>(fn))
|
||||
cc = fun->getCallingConv();
|
||||
namespace {
|
||||
|
||||
if (value->getType() != IGM.ObjCPtrTy) {
|
||||
auto fnTy = llvm::FunctionType::get(IGM.VoidTy, value->getType(),
|
||||
false)->getPointerTo();
|
||||
fn = llvm::ConstantExpr::getBitCast(fn, fnTy);
|
||||
/// A utility class that saves the original type of a value in its constructor,
|
||||
/// casts the value to i8*, and then allows values later to be casted to the
|
||||
/// original type.
|
||||
struct CastToInt8PtrTy {
|
||||
llvm::Type *OrigTy;
|
||||
|
||||
CastToInt8PtrTy(IRGenFunction &IGF, llvm::Value *&value)
|
||||
: OrigTy(value->getType()) {
|
||||
if (OrigTy->isPointerTy())
|
||||
value = IGF.Builder.CreateBitCast(value, IGF.IGM.Int8PtrTy);
|
||||
else
|
||||
value = IGF.Builder.CreateIntToPtr(value, IGF.IGM.Int8PtrTy);
|
||||
}
|
||||
|
||||
auto call = Builder.CreateCall(fn, value);
|
||||
call->setCallingConv(cc);
|
||||
call->setDoesNotThrow();
|
||||
llvm::Value *restore(IRGenFunction &IGF, llvm::Value *value) const {
|
||||
assert(value->getType() == IGF.IGM.Int8PtrTy);
|
||||
if (OrigTy->isPointerTy())
|
||||
return IGF.Builder.CreateBitCast(value, OrigTy);
|
||||
else
|
||||
return IGF.Builder.CreatePtrToInt(value, OrigTy);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// Given a function of type %objc* (%objc*)*, cast it as appropriate
|
||||
/// to be used with values of type T.
|
||||
static llvm::Constant *getCastOfRetainFn(IRGenModule &IGM,
|
||||
llvm::Constant *fn,
|
||||
llvm::Type *valueTy) {
|
||||
#ifndef NDEBUG
|
||||
auto origFnTy = cast<llvm::FunctionType>(fn->getType()->getPointerElementType());
|
||||
assert(origFnTy->getReturnType() == IGM.ObjCPtrTy);
|
||||
assert(origFnTy->getNumParams() == 1);
|
||||
assert(origFnTy->getParamType(0) == IGM.ObjCPtrTy);
|
||||
assert(isa<llvm::PointerType>(valueTy) ||
|
||||
valueTy == IGM.IntPtrTy); // happens with optional types
|
||||
#endif
|
||||
if (valueTy == IGM.ObjCPtrTy)
|
||||
return fn;
|
||||
|
||||
auto fnTy = llvm::FunctionType::get(valueTy, valueTy, false);
|
||||
return llvm::ConstantExpr::getBitCast(fn, fnTy->getPointerTo(0));
|
||||
void IRGenFunction::emitObjCStrongRelease(llvm::Value *value) {
|
||||
CastToInt8PtrTy savedType(*this, value);
|
||||
Builder.CreateIntrinsicCall(llvm::Intrinsic::objc_release, value);
|
||||
}
|
||||
|
||||
void IRGenFunction::emitObjCStrongRetain(llvm::Value *v) {
|
||||
@@ -100,28 +94,16 @@ void IRGenFunction::emitObjCStrongRetain(llvm::Value *v) {
|
||||
}
|
||||
|
||||
llvm::Value *IRGenFunction::emitObjCRetainCall(llvm::Value *value) {
|
||||
// Get an appropriately cast function pointer.
|
||||
auto fn = IGM.getObjCRetainFn();
|
||||
auto cc = IGM.C_CC;
|
||||
if (auto fun = dyn_cast<llvm::Function>(fn))
|
||||
cc = fun->getCallingConv();
|
||||
fn = getCastOfRetainFn(IGM, fn, value->getType());
|
||||
|
||||
auto call = Builder.CreateCall(fn, value);
|
||||
call->setCallingConv(cc);
|
||||
call->setDoesNotThrow();
|
||||
return call;
|
||||
CastToInt8PtrTy savedType(*this, value);
|
||||
auto call = Builder.CreateIntrinsicCall(llvm::Intrinsic::objc_retain, value);
|
||||
return savedType.restore(*this, call);
|
||||
}
|
||||
|
||||
llvm::Value *IRGenFunction::emitObjCAutoreleaseCall(llvm::Value *val) {
|
||||
if (val->getType()->isPointerTy())
|
||||
val = Builder.CreateBitCast(val, IGM.ObjCPtrTy);
|
||||
else
|
||||
val = Builder.CreateIntToPtr(val, IGM.ObjCPtrTy);
|
||||
|
||||
auto call = Builder.CreateCall(IGM.getObjCAutoreleaseFn(), val);
|
||||
call->setDoesNotThrow();
|
||||
return call;
|
||||
llvm::Value *IRGenFunction::emitObjCAutoreleaseCall(llvm::Value *value) {
|
||||
CastToInt8PtrTy savedType(*this, value);
|
||||
auto call = Builder.CreateIntrinsicCall(llvm::Intrinsic::objc_autorelease,
|
||||
value);
|
||||
return savedType.restore(*this, call);
|
||||
}
|
||||
|
||||
llvm::InlineAsm *IRGenModule::getObjCRetainAutoreleasedReturnValueMarker() {
|
||||
@@ -173,20 +155,10 @@ llvm::Value *irgen::emitObjCRetainAutoreleasedReturnValue(IRGenFunction &IGF,
|
||||
IGF.Builder.CreateAsmCall(marker, {});
|
||||
}
|
||||
|
||||
auto fn = IGF.IGM.getObjCRetainAutoreleasedReturnValueFn();
|
||||
CastToInt8PtrTy savedType(IGF, value);
|
||||
|
||||
// We don't want to cast the function here because it interferes with
|
||||
// LLVM's ability to recognize and special-case this function.
|
||||
// Note that the parameter and result must also have type i8*.
|
||||
llvm::Type *valueType = value->getType();
|
||||
if (isa<llvm::PointerType>(valueType)) {
|
||||
value = IGF.Builder.CreateBitCast(value, IGF.IGM.Int8PtrTy);
|
||||
} else {
|
||||
value = IGF.Builder.CreateIntToPtr(value, IGF.IGM.Int8PtrTy);
|
||||
}
|
||||
|
||||
auto call = IGF.Builder.CreateCall(fn, value);
|
||||
call->setDoesNotThrow();
|
||||
auto call = IGF.Builder.CreateIntrinsicCall(
|
||||
llvm::Intrinsic::objc_retainAutoreleasedReturnValue, value);
|
||||
|
||||
const llvm::Triple &triple = IGF.IGM.Context.LangOpts.Target;
|
||||
if (triple.getArch() == llvm::Triple::x86_64) {
|
||||
@@ -199,25 +171,19 @@ llvm::Value *irgen::emitObjCRetainAutoreleasedReturnValue(IRGenFunction &IGF,
|
||||
call->setTailCallKind(llvm::CallInst::TCK_NoTail);
|
||||
}
|
||||
|
||||
llvm::Value *result = call;
|
||||
if (isa<llvm::PointerType>(valueType)) {
|
||||
result = IGF.Builder.CreateBitCast(result, valueType);
|
||||
} else {
|
||||
result = IGF.Builder.CreatePtrToInt(result, valueType);
|
||||
}
|
||||
return result;
|
||||
return savedType.restore(IGF, call);
|
||||
}
|
||||
|
||||
/// Autorelease a return value.
|
||||
llvm::Value *irgen::emitObjCAutoreleaseReturnValue(IRGenFunction &IGF,
|
||||
llvm::Value *value) {
|
||||
auto fn = IGF.IGM.getObjCAutoreleaseReturnValueFn();
|
||||
fn = getCastOfRetainFn(IGF.IGM, fn, value->getType());
|
||||
CastToInt8PtrTy savedType(IGF, value);
|
||||
|
||||
auto call = IGF.Builder.CreateCall(fn, value);
|
||||
auto call = IGF.Builder.CreateIntrinsicCall(
|
||||
llvm::Intrinsic::objc_autoreleaseReturnValue, value);
|
||||
call->setDoesNotThrow();
|
||||
call->setTailCall(); // force tail calls at -O0
|
||||
return call;
|
||||
return savedType.restore(IGF, call);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -8,7 +8,7 @@ class Sub: Base {
|
||||
// CHECK: [[OPAQUE_SELF:%.+]] = bitcast %TSo4BaseC* %2 to {{%.+}}*
|
||||
// CHECK: [[RESULT:%.+]] = call {{%.+}}* bitcast (void ()* @objc_msgSend to {{%.+}}* ({{%.+}}*, i8*)*)({{%.+}}* [[OPAQUE_SELF]], i8* [[SELECTOR]])
|
||||
// CHECK: [[OPAQUE_RESULT:%.+]] = bitcast {{%.+}}* [[RESULT]] to i8*
|
||||
// CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* [[OPAQUE_RESULT]])
|
||||
// CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[OPAQUE_RESULT]])
|
||||
_ = self.getClassInstanceWithoutMentioningItsName()
|
||||
// CHECK: call void @swift_release(%swift.refcounted* {{%.+}})
|
||||
// CHECK: ret void
|
||||
|
||||
@@ -34,7 +34,7 @@ func instanceMethods(_ b: B) {
|
||||
func extensionMethods(b b: B) {
|
||||
// CHECK: load i8*, i8** @"\01L_selector(method:separateExtMethod:)", align 8
|
||||
// CHECK: [[T0:%.*]] = call i8* bitcast (void ()* @objc_msgSend to i8*
|
||||
// CHECK-NEXT: [[T1:%.*]] = {{.*}}call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
|
||||
// CHECK-NEXT: [[T1:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
|
||||
// CHECK-NOT: [[T0]]
|
||||
// CHECK: [[T1]]
|
||||
b.method(1, separateExtMethod:1.5)
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu %s
|
||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu -DINT=i%target-ptrsize %s
|
||||
|
||||
// rdar://16565958
|
||||
|
||||
import Builtin
|
||||
import Swift
|
||||
|
||||
// CHECK: [[OBJC:%objc_object]] = type
|
||||
|
||||
class C {}
|
||||
sil_vtable C {}
|
||||
sil [ossa] @_TFC11autorelease1Cd : $@convention(method) (@owned C) -> @owned Builtin.NativeObject {
|
||||
@@ -20,13 +18,11 @@ bb0(%0 : @owned $C?):
|
||||
return %0 : $C?
|
||||
}
|
||||
|
||||
// CHECK-32: define{{( dllexport| protected)?}} swiftcc i32 @foo(i32) {{.*}} {
|
||||
// CHECK-32: [[T0:%.*]] = tail call i32 bitcast ([[OBJC]]* ([[OBJC]]*)* @objc_autoreleaseReturnValue to i32 (i32)*)(i32 %0)
|
||||
// CHECK-32-NEXT: ret i32 [[T0]]
|
||||
|
||||
// CHECK-64: define{{( dllexport| protected)?}} swiftcc i64 @foo(i64) {{.*}} {
|
||||
// CHECK-64: [[T0:%.*]] = tail call i64 bitcast ([[OBJC]]* ([[OBJC]]*)* @objc_autoreleaseReturnValue to i64 (i64)*)(i64 %0)
|
||||
// CHECK-64-NEXT: ret i64 [[T0]]
|
||||
// CHECK: define{{( dllexport| protected)?}} swiftcc [[INT]] @foo([[INT]]) {{.*}} {
|
||||
// CHECK: [[T0:%.*]] = inttoptr [[INT]] %0 to i8*
|
||||
// CHECK-NEXT: [[T1:%.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* [[T0]])
|
||||
// CHECK-NEXT: [[T2:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
|
||||
// CHECK-NEXT: ret [[INT]] [[T2]]
|
||||
|
||||
sil [ossa] @bar : $@convention(thin) (@owned C?) -> @owned C? {
|
||||
bb0(%0 : @owned $C?):
|
||||
@@ -38,7 +34,7 @@ bb0(%0 : @owned $C?):
|
||||
// x86_64: define{{( dllexport| protected)?}} swiftcc i64 @bar(i64)
|
||||
// x86_64: [[T0:%.*]] = call swiftcc i64 @foo(i64 %0)
|
||||
// x86_64-NEXT: [[T1:%.*]] = inttoptr i64 [[T0]] to i8*
|
||||
// x86_64-NEXT: [[T2:%.*]] = notail call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// x86_64-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// x86_64-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i64
|
||||
// x86_64-NEXT: ret i64 [[T3]]
|
||||
|
||||
@@ -46,14 +42,14 @@ bb0(%0 : @owned $C?):
|
||||
// arm64: [[T0:%.*]] = call swiftcc i64 @foo(i64 %0)
|
||||
// arm64-NEXT: call void asm sideeffect "mov
|
||||
// arm64-NEXT: [[T1:%.*]] = inttoptr i64 [[T0]] to i8*
|
||||
// arm64-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// arm64-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// arm64-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i64
|
||||
// arm64-NEXT: ret i64 [[T3]]
|
||||
|
||||
// i386: define{{( dllexport| protected)?}} swiftcc i32 @bar(i32)
|
||||
// i386: [[T0:%.*]] = call swiftcc i32 @foo(i32 %0)
|
||||
// i386-NEXT: [[T1:%.*]] = inttoptr i32 [[T0]] to i8*
|
||||
// i386-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// i386-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// i386-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i32
|
||||
// i386-NEXT: ret i32 [[T3]]
|
||||
|
||||
@@ -61,7 +57,7 @@ bb0(%0 : @owned $C?):
|
||||
// armv7: [[T0:%.*]] = call swiftcc i32 @foo(i32 %0)
|
||||
// armv7-NEXT: call void asm sideeffect "mov
|
||||
// armv7-NEXT: [[T1:%.*]] = inttoptr i32 [[T0]] to i8*
|
||||
// armv7-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// armv7-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// armv7-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i32
|
||||
// armv7-NEXT: ret i32 [[T3]]
|
||||
|
||||
@@ -69,7 +65,7 @@ bb0(%0 : @owned $C?):
|
||||
// armv7s: [[T0:%.*]] = call swiftcc i32 @foo(i32 %0)
|
||||
// armv7s-NEXT: call void asm sideeffect "mov
|
||||
// armv7s-NEXT: [[T1:%.*]] = inttoptr i32 [[T0]] to i8*
|
||||
// armv7s-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// armv7s-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// armv7s-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i32
|
||||
// armv7s-NEXT: ret i32 [[T3]]
|
||||
|
||||
@@ -77,6 +73,6 @@ bb0(%0 : @owned $C?):
|
||||
// armv7k: [[T0:%.*]] = call swiftcc i32 @foo(i32 %0)
|
||||
// armv7k-NEXT: call void asm sideeffect "mov
|
||||
// armv7k-NEXT: [[T1:%.*]] = inttoptr i32 [[T0]] to i8*
|
||||
// armv7k-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// armv7k-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
|
||||
// armv7k-NEXT: [[T3:%.*]] = ptrtoint i8* [[T2]] to i32
|
||||
// armv7k-NEXT: ret i32 [[T3]]
|
||||
|
||||
@@ -105,8 +105,8 @@ bb0(%0 : $@thick C.Type):
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %T5class1CC* @autorelease(%T5class1CC*) {{.*}} {
|
||||
// CHECK: %1 = bitcast %T5class1CC* %0 to %objc_object*
|
||||
// CHECK: call %objc_object* @objc_autorelease(%objc_object* %1)
|
||||
// CHECK: %1 = bitcast %T5class1CC* %0 to i8*
|
||||
// CHECK: call i8* @llvm.objc.autorelease(i8* %1)
|
||||
// CHECK: ret %T5class1CC* %0
|
||||
sil @autorelease : $@convention(thin) (@owned C) -> C {
|
||||
entry(%c : $C):
|
||||
@@ -115,8 +115,8 @@ entry(%c : $C):
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @autorelease_optional(i64) {{.*}} {
|
||||
// CHECK: %1 = inttoptr i64 %0 to %objc_object*
|
||||
// CHECK: call %objc_object* @objc_autorelease(%objc_object* %1)
|
||||
// CHECK: %1 = inttoptr i64 %0 to i8*
|
||||
// CHECK: call i8* @llvm.objc.autorelease(i8* %1)
|
||||
// CHECK: ret i64 %0
|
||||
sil @autorelease_optional : $@convention(thin) (@owned C?) -> C? {
|
||||
entry(%c : $C?):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %build-irgen-test-overlays
|
||||
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t -I %S/../IDE/Inputs/custom-modules) %s -emit-ir | %FileCheck %s
|
||||
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t -I %S/../IDE/Inputs/custom-modules) %s -emit-ir -O | %FileCheck %s -check-prefix=OPT
|
||||
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t -I %S/../IDE/Inputs/custom-modules) %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
|
||||
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t -I %S/../IDE/Inputs/custom-modules) %s -emit-ir -O | %FileCheck %s -check-prefix=OPT -DINT=i%target-ptrsize
|
||||
import CoreFoundation
|
||||
import Foundation
|
||||
import Newtype
|
||||
@@ -133,18 +133,23 @@ public func anchor() -> Bool {
|
||||
|
||||
class ObjCTest {
|
||||
// CHECK-LABEL: define hidden %0* @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo"
|
||||
// CHECK: [[CASTED:%.+]] = ptrtoint %0* %2 to i{{32|64}}
|
||||
// CHECK: [[RESULT:%.+]] = call swiftcc i{{32|64}} @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGF"(i{{32|64}} [[CASTED]], %T7newtype8ObjCTestC* swiftself {{%.+}})
|
||||
// CHECK: [[AUTORELEASE_RESULT:%.+]] = {{(tail )?}}call {{.*}} @objc_autoreleaseReturnValue {{.*}}(i{{32|64}} [[RESULT]])
|
||||
// CHECK: [[OPAQUE_RESULT:%.+]] = inttoptr i{{32|64}} [[AUTORELEASE_RESULT]] to %0*
|
||||
// CHECK: [[CASTED:%.+]] = ptrtoint %0* %2 to [[INT]]
|
||||
// CHECK: [[RESULT:%.+]] = call swiftcc [[INT]] @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGF"([[INT]] [[CASTED]], %T7newtype8ObjCTestC* swiftself {{%.+}})
|
||||
// CHECK: [[CAST_RESULT:%.+]] = inttoptr [[INT]] [[RESULT]] to i8*
|
||||
// CHECK: [[AUTORELEASE_RESULT:%.+]] = {{(tail )?}}call i8* @llvm.objc.autoreleaseReturnValue(i8* [[CAST_RESULT]])
|
||||
// CHECK: [[CAST_AUTORELEASE_RESULT:%.+]] = ptrtoint i8* [[AUTORELEASE_RESULT]] to [[INT]]
|
||||
// CHECK: [[OPAQUE_RESULT:%.+]] = inttoptr [[INT]] [[CAST_AUTORELEASE_RESULT]] to %0*
|
||||
// CHECK: ret %0* [[OPAQUE_RESULT]]
|
||||
// CHECK: {{^}$}}
|
||||
|
||||
// OPT-LABEL: define hidden %0* @"$s7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo"
|
||||
// OPT: [[CAST_VALUE:%.*]] = bitcast %0* %2 to %objc_object*
|
||||
// OPT: [[RESULT:%.*]] = {{(tail )?}}call %objc_object* @objc_autoreleaseReturnValue(%objc_object* [[CAST_VALUE]])
|
||||
// OPT: [[RESULT_CAST:%.*]] = bitcast %objc_object* [[RESULT]] to %0*
|
||||
// OPT: ret %0* [[RESULT_CAST]]
|
||||
// OPT: [[RECAST_VALUE:%.*]] = bitcast %objc_object* [[CAST_VALUE]] to i8*
|
||||
// OPT: [[RESULT:%.*]] = {{(tail )?}}call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* [[RECAST_VALUE]])
|
||||
// OPT: [[RESULT_CAST:%.*]] = bitcast i8* [[RESULT]] to %0*
|
||||
// OPT: [[RESULT_RECAST:%.*]] = bitcast %0* [[RESULT_CAST]] to i8*
|
||||
// OPT: [[RESULT_RERECAST:%.*]] = bitcast i8* [[RESULT_RECAST]] to %0*
|
||||
// OPT: ret %0* [[RESULT_RERECAST]]
|
||||
// OPT: {{^}$}}
|
||||
@objc func optionalPassThrough(_ ed: ErrorDomain?) -> ErrorDomain? {
|
||||
return ed
|
||||
|
||||
@@ -48,7 +48,7 @@ class MyBlammo : Blammo {
|
||||
class Test2 : Gizmo {
|
||||
func foo() {}
|
||||
// CHECK: define hidden swiftcc void @"$s4objc5Test2C3fooyyF"([[TEST2]]* swiftself) {{.*}} {
|
||||
// CHECK: call {{.*}} @objc_release
|
||||
// CHECK: call {{.*}} @llvm.objc.release
|
||||
// CHECK: ret void
|
||||
|
||||
@objc dynamic func bar() {}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
// REQUIRES: objc_interop
|
||||
// REQUIRES: asserts
|
||||
|
||||
// CHECK-WITHOUT-PASS: call void (...) @clang.arc.use
|
||||
// CHECK-WITH-PASS-NOT: call void (...) @clang.arc.use
|
||||
// CHECK-WITHOUT-PASS: call void (...) @llvm.objc.clang.arc.use
|
||||
// CHECK-WITH-PASS-NOT: call void (...) @llvm.objc.clang.arc.use
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ sil_vtable SwiftClass {}
|
||||
protocol ClassProto : class {}
|
||||
|
||||
// CHECK-LABEL: define hidden swiftcc %TSo8NSObjectC* @checkedClassBoundCast(%swift.type*, %TSo8NSObjectC*, %swift.type* %T) #0 {
|
||||
// CHECK: [[OBJ:%.+]] = bitcast %TSo8NSObjectC* %1 to i8*
|
||||
// CHECK: call i8* @llvm.objc.retain(i8* [[OBJ]])
|
||||
// CHECK: [[OPAQUE_OBJ:%.+]] = bitcast %TSo8NSObjectC* %1 to i8*
|
||||
// CHECK: [[OPAQUE_CLASS:%.+]] = bitcast %swift.type* %T to i8*
|
||||
// CHECK: [[OPAQUE_RESULT:%.+]] = call i8* @swift_dynamicCastUnknownClassUnconditional(i8* [[OPAQUE_OBJ]], i8* [[OPAQUE_CLASS]], {{.*}})
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// CHECK-DAG: [[NSRECT:%TSo6NSRectV]] = type <{ %TSo7NSPointV, %TSo6NSSizeV }>
|
||||
// CHECK-DAG: [[NSPOINT:%TSo7NSPointV]] = type <{ %TSd, %TSd }>
|
||||
// CHECK-DAG: [[NSSIZE:%TSo6NSSizeV]] = type <{ %TSd, %TSd }>
|
||||
// CHECK-DAG: [[OBJC:%objc_object]] = type opaque
|
||||
|
||||
// CHECK: @"OBJC_METACLASS_$__TtC17objc_class_export3Foo" = hidden global %objc_class {
|
||||
// CHECK-SAME: %objc_class* @"OBJC_METACLASS_$_{{(_TtCs12_)?}}SwiftObject",
|
||||
|
||||
@@ -24,7 +24,7 @@ bb0(%0 : $Optional<Bee>, %1 : $@thick Hive.Type):
|
||||
%3 = objc_method %2 : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive> // user: %4
|
||||
// CHECK: call {{.*}} @objc_msgSend
|
||||
%4 = apply %3(%0, %2) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive> // users: %5, %6
|
||||
// CHECK: call {{.*}} @objc_autorelease
|
||||
// CHECK: call {{.*}} @llvm.objc.autorelease
|
||||
autorelease_value %4 : $Optional<Hive>
|
||||
return %4 : $Optional<Hive>
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
class Foo {
|
||||
// CHECK-LABEL: define hidden swiftcc void @"$s21objc_layout_multifile3FooC3barAA3BarCSgvs"
|
||||
// CHECK-NOT: ret
|
||||
// CHECK: @objc_retain
|
||||
// CHECK: @llvm.objc.retain
|
||||
var bar: Bar?
|
||||
}
|
||||
|
||||
@@ -22,6 +22,6 @@ import Foundation
|
||||
// CHECK-LABEL: s13objc_pointers14returnNSObject3objSo0D0CAE_tF
|
||||
func returnNSObject(obj: NSObject) -> NSObject {
|
||||
// CHECK-NOT: return
|
||||
// CHECK: @objc_retain
|
||||
// CHECK: @llvm.objc.retain
|
||||
return obj
|
||||
}
|
||||
|
||||
@@ -28,11 +28,11 @@ public func test(_ dict: NSDictionary) {
|
||||
// CHECK-LABEL: define {{.*}}swiftcc void @"$s34objc_retainAutoreleasedReturnValue4testyySo12NSDictionaryCFyADXEfU_"(%TSo12NSDictionaryC*)
|
||||
// CHECK: entry:
|
||||
// CHECK: call {{.*}}@objc_msgSend
|
||||
// CHECK: notail call i8* @objc_retainAutoreleasedReturnValue
|
||||
// CHECK: notail call i8* @llvm.objc.retainAutoreleasedReturnValue
|
||||
// CHECK: ret void
|
||||
|
||||
// OPT-LABEL: define {{.*}}swiftcc void @"$s34objc_retainAutoreleasedReturnValue4testyySo12NSDictionaryCFyADXEfU_"(%TSo12NSDictionaryC*)
|
||||
// OPT: entry:
|
||||
// OPT: call {{.*}}@objc_msgSend
|
||||
// OPT: notail call i8* @objc_retainAutoreleasedReturnValue
|
||||
// OPT: notail call i8* @llvm.objc.retainAutoreleasedReturnValue
|
||||
// OPT: ret void
|
||||
|
||||
@@ -105,7 +105,8 @@ class GenericRuncer<T> : Gizmo {
|
||||
// CHECK: [[OPTIONALADDR:%.*]] = bitcast %TSo5GizmoCSg* [[XADDR]] to i64*
|
||||
// CHECK: [[OPTIONAL:%.*]] = load i64, i64* [[OPTIONALADDR]]
|
||||
// CHECK: [[OBJ:%.*]] = inttoptr i64 [[OPTIONAL]] to %objc_object*
|
||||
// CHECK: call %objc_object* @objc_retain(%objc_object* [[OBJ]]
|
||||
// CHECK: [[OBJ_CAST:%.*]] = bitcast %objc_object* [[OBJ]] to i8*
|
||||
// CHECK: call i8* @llvm.objc.retain(i8* [[OBJ_CAST]])
|
||||
// CHECK: ret i64 [[OPTIONAL]]
|
||||
|
||||
// CHECK: define hidden swiftcc void @"$s10objc_super13GenericRuncerC5runceyyFZ"(%swift.type* swiftself) {{.*}} {
|
||||
|
||||
@@ -143,7 +143,8 @@ entry(%c : $ObjCClass):
|
||||
// CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* %0 to [[DATA_TYPE]]*
|
||||
// CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1
|
||||
// CHECK: [[SELF:%.*]] = load %T18partial_apply_objc9ObjCClassC*, %T18partial_apply_objc9ObjCClassC** [[X_ADDR]], align 8
|
||||
// CHECK: call {{.*}}@objc_retain{{.*}}(%{{.*}}* [[SELF]])
|
||||
// CHECK: [[T0:%.*]] = bitcast %T18partial_apply_objc9ObjCClassC* [[SELF]] to i8*
|
||||
// CHECK: call i8* @llvm.objc.retain(i8* [[T0]])
|
||||
// CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(fakeInitFamily)", align 8
|
||||
// CHECK: [[I8PTRSELF:%.*]] = bitcast %T18partial_apply_objc9ObjCClassC* [[SELF]] to [[OPAQUE4:%.*]]*
|
||||
// CHECK: call [[OPAQUE3:%.*]]* bitcast (void ()* @objc_msgSend to [[OPAQUE3]]* ([[OPAQUE4:%.*]]*, i8*)*)([[OPAQUE4]]* [[I8PTRSELF]], i8* [[CMD]])
|
||||
|
||||
Reference in New Issue
Block a user