1// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck -check-prefix=ARM64 -check-prefix=COMMON %s 2// RUN: %clang_cc1 -triple thumbv7-apple-ios10 -fobjc-arc -fblocks -fobjc-runtime=ios-10.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s 3// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13 -fobjc-arc -fblocks -fobjc-runtime=macosx-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s 4// RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-arc -fblocks -fobjc-runtime=macosx-fragile-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s 5 6typedef void (^BlockTy)(void); 7 8// COMMON: %[[STRUCT_WEAK:.*]] = type { i32, i8* } 9 10typedef struct { 11 int f0; 12 __weak id f1; 13} Weak; 14 15Weak getWeak(void); 16void calleeWeak(Weak); 17 18// ARM64: define{{.*}} void @test_constructor_destructor_Weak() 19// ARM64: %[[T:.*]] = alloca %[[STRUCT_WEAK]], align 8 20// ARM64: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8** 21// ARM64: call void @__default_constructor_8_w8(i8** %[[V0]]) 22// ARM64: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8** 23// ARM64: call void @__destructor_8_w8(i8** %[[V1]]) 24// ARM64: ret void 25 26// ARM64: define linkonce_odr hidden void @__default_constructor_8_w8(i8** %[[DST:.*]]) 27// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 28// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 29// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 30// ARM64: %[[V1]] = bitcast i8** %[[V0]] to i8* 31// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8 32// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** 33// ARM64: %[[V4:.*]] = bitcast i8** %[[V3]] to i8* 34// ARM64: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false) 35 36// ARM64: define linkonce_odr hidden void @__destructor_8_w8(i8** %[[DST:.*]]) 37// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 38// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 39// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 40// ARM64: %[[V1:.*]] = bitcast i8** %[[V0]] to i8* 41// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8 42// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8** 43// ARM64: call void @llvm.objc.destroyWeak(i8** %[[V3]]) 44 45@interface C 46- (void)m:(Weak)a; 47@end 48 49void test_constructor_destructor_Weak(void) { 50 Weak t; 51} 52 53// ARM64: define{{.*}} void @test_copy_constructor_Weak(%[[STRUCT_WEAK]]* %{{.*}}) 54// ARM64: call void @__copy_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}}) 55// ARM64: call void @__destructor_8_w8(i8** %{{.*}}) 56 57// ARM64: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) 58// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 59// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 60// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 61// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 62// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 63// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 64// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* 65// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* 66// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 67// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 68// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* 69// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 70// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** 71// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* 72// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 73// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** 74// ARM64: call void @llvm.objc.copyWeak(i8** %[[V7]], i8** %[[V10]]) 75 76void test_copy_constructor_Weak(Weak *s) { 77 Weak t = *s; 78} 79 80// ARM64: define{{.*}} void @test_copy_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}}, %[[STRUCT_WEAK]]* %{{.*}}) 81// ARM64: call void @__copy_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}}) 82 83// ARM64: define linkonce_odr hidden void @__copy_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) 84// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 85// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 86// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 87// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 88// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 89// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 90// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* 91// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* 92// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 93// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 94// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* 95// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 96// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** 97// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* 98// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 99// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** 100// ARM64: %[[V11:.*]] = call i8* @llvm.objc.loadWeakRetained(i8** %[[V10]]) 101// ARM64: %[[V12:.*]] = call i8* @llvm.objc.storeWeak(i8** %[[V7]], i8* %[[V11]]) 102// ARM64: call void @llvm.objc.release(i8* %[[V11]]) 103 104void test_copy_assignment_Weak(Weak *d, Weak *s) { 105 *d = *s; 106} 107 108// ARM64: define internal void @__Block_byref_object_copy_(i8* %0, i8* %1) 109// ARM64: call void @__move_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}}) 110 111// ARM64: define linkonce_odr hidden void @__move_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) 112// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 113// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 114// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 115// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 116// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 117// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 118// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* 119// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* 120// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 121// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 122// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* 123// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 124// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** 125// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* 126// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 127// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** 128// ARM64: call void @llvm.objc.moveWeak(i8** %[[V7]], i8** %[[V10]]) 129 130void test_move_constructor_Weak(void) { 131 __block Weak t; 132 BlockTy b = ^{ (void)t; }; 133} 134 135// ARM64: define{{.*}} void @test_move_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}}) 136// ARM64: call void @__move_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}}) 137 138// ARM64: define linkonce_odr hidden void @__move_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]]) 139// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8 140// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8 141// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8 142// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8 143// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8 144// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8 145// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32* 146// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32* 147// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8 148// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8 149// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8* 150// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8 151// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8** 152// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8* 153// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8 154// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8** 155// ARM64: %[[V11:.*]] = call i8* @llvm.objc.loadWeakRetained(i8** %[[V10]]) 156// ARM64: %[[V12:.*]] = call i8* @llvm.objc.storeWeak(i8** %[[V7]], i8* %[[V11]]) 157// ARM64: call void @llvm.objc.destroyWeak(i8** %[[V10]]) 158// ARM64: call void @llvm.objc.release(i8* %[[V11]]) 159 160void test_move_assignment_Weak(Weak *p) { 161 *p = getWeak(); 162} 163 164// COMMON: define{{.*}} void @test_parameter_Weak(%[[STRUCT_WEAK]]* %[[A:.*]]) 165// COMMON: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[A]] to i8** 166// COMMON: call void @__destructor_{{.*}}(i8** %[[V0]]) 167 168void test_parameter_Weak(Weak a) { 169} 170 171// COMMON: define{{.*}} void @test_argument_Weak(%[[STRUCT_WEAK]]* %[[A:.*]]) 172// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]* 173// COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]] 174// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]] 175// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]] 176// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8** 177// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8** 178// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]]) 179// COMMON: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]]) 180// COMMON-NEXT: ret 181 182void test_argument_Weak(Weak *a) { 183 calleeWeak(*a); 184} 185 186// COMMON: define{{.*}} void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret(%[[STRUCT_WEAK]]) align {{.*}} %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]]) 187// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]* 188// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]] 189// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]] 190// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8** 191// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8** 192// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]]) 193// COMMON: ret void 194 195Weak test_return_Weak(Weak *a) { 196 return *a; 197} 198 199// COMMON-LABEL: define{{.*}} void @test_null_receiver( 200// COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]] 201// COMMON: br i1 202 203// COMMON: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %[[STRUCT_WEAK]]*)*)({{.*}}, %[[STRUCT_WEAK]]* %[[AGG_TMP]]) 204// COMMON: br 205 206// COMMON: %[[V6:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8** 207// COMMON: call void @__destructor_{{.*}}(i8** %[[V6]]) 208// COMMON: br 209 210void test_null_receiver(C *c) { 211 [c m:getWeak()]; 212} 213