Use the new ObjC retain/release intrinsics in IRGen.

This commit is contained in:
John McCall
2019-01-26 16:46:21 -05:00
committed by Bob Wilson
parent 8719f5276c
commit b45ca0439b
17 changed files with 87 additions and 128 deletions

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)

View File

@@ -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]]

View File

@@ -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?):

View File

@@ -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

View File

@@ -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() {}

View File

@@ -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

View File

@@ -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]], {{.*}})

View File

@@ -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",

View File

@@ -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>
}

View File

@@ -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?
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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) {{.*}} {

View File

@@ -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]])