20 changes: 19 additions & 1 deletion clang/test/CodeGenObjC/arc-blocks.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ void test3(void (^sink)(id*)) {
// CHECK-NEXT: call i8* @objc_retain(
// CHECK-NEXT: bitcast i8*
// CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
// CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
// CHECK-NEXT: store i8* null, i8** [[STRONG]]

// CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
Expand All @@ -94,6 +96,8 @@ void test3(void (^sink)(id*)) {

// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[STRONG]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])

// CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
// CHECK-NEXT: bitcast
Expand Down Expand Up @@ -167,6 +171,8 @@ void test5(void) {
// CHECK-LABEL: define void @test5()
// CHECK: [[VAR:%.*]] = alloca i8*
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast i8** [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[VARPTR1]])
// CHECK: [[T0:%.*]] = call i8* @test5_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
Expand All @@ -178,6 +184,8 @@ void test5(void) {
// CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK: call void @test5_helper
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast i8** [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[VARPTR2]])
// CHECK-NEXT: ret void
}

Expand All @@ -190,6 +198,8 @@ void test6(void) {
// CHECK-LABEL: define void @test6()
// CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 48, i8* [[VARPTR1]])
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 2
// 0x02000000 - has copy/dispose helpers weak
// CHECK-NEXT: store i32 1107296256, i32* [[T0]]
Expand All @@ -207,7 +217,9 @@ void test6(void) {
// CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
// CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
// CHECK: ret void
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 48, i8* [[VARPTR2]])
// CHECK-NEXT: ret void

// CHECK-LABEL: define internal void @__Block_byref_object_copy_
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6
Expand Down Expand Up @@ -494,6 +506,8 @@ void test13(id x) {
// CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
// CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BPTR1]])
// CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8
// CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
Expand All @@ -519,6 +533,8 @@ void test13(id x) {
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
// CHECK-NEXT: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[BPTR2]])

// CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]]
// CHECK-NEXT: br i1 [[T0]]
Expand Down Expand Up @@ -550,6 +566,8 @@ void test16() {
// CHECK-LABEL: define void @test16(
// CHECK: [[BLKVAR:%.*]] = alloca void ()*, align 8
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[BLKVARPTR1:%.*]] = bitcast void ()** [[BLKVAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BLKVARPTR1]])
// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: store void ()* null, void ()** [[BLKVAR]], align 8
}
Expand Down
11 changes: 10 additions & 1 deletion clang/test/CodeGenObjC/arc-bridged-cast.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ void bridge_transfer_from_cf(int *i) {
// CHECK: store i32 17
*i = 17;
// CHECK: call void @objc_release
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

Expand All @@ -50,6 +52,8 @@ void bridge_from_cf(int *i) {
// CHECK: store i32 17
*i = 17;
// CHECK: call void @objc_release
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

Expand All @@ -67,14 +71,17 @@ void bridge_retained_of_cf(int *i) {
// CHECK: store i32 13
// CHECK: store i32 17
*i = 17;
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

// CHECK-LABEL: define void @bridge_of_cf
void bridge_of_cf(int *i) {
// CHECK: store i32 7
*i = 7;
// CHECK: call i8* @CreateSomething()
// CHECK: call void @llvm.lifetime.start
// CHECK-NEXT: call i8* @CreateSomething()
CFTypeRef cf1 = (__bridge CFTypeRef)CreateSomething();
// CHECK-NOT: retain
// CHECK: store i32 11
Expand All @@ -85,6 +92,8 @@ void bridge_of_cf(int *i) {
// CHECK-NOT: release
// CHECK: store i32 17
*i = 17;
// CHECK-NEXT: bitcast
// CHECK-NEXT: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

4 changes: 4 additions & 0 deletions clang/test/CodeGenObjC/arc-literals.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ void test_numeric() {
// CHECK: call i8* @objc_retainAutoreleasedReturnValue
id charlit = @'a';
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

Expand Down
44 changes: 44 additions & 0 deletions clang/test/CodeGenObjC/arc-precise-lifetime.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ void test0() {
PRECISE_LIFETIME id x = test0_helper();
x = 0;
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper()
// CHECK-NEXT: store i8* [[CALL]], i8** [[X]]

Expand All @@ -19,6 +21,8 @@ void test0() {
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]]
// CHECK-NOT: clang.imprecise_release

// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
}

Expand All @@ -32,11 +36,17 @@ - (char*) interior __attribute__((objc_returns_inner_pointer));

// CHECK-LABEL: define void @test1a()
void test1a(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
Expand All @@ -45,41 +55,61 @@ void test1a(void) {
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
// CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T6]], i8**
// CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
Test1 *ptr = test1_helper();
char *c = [(ptr) interior];
}

// CHECK-LABEL: define void @test1b()
void test1b(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T3]], i8**
// CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
__attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
char *c = [ptr interior];
}

void test1c(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
Expand All @@ -88,20 +118,30 @@ void test1c(void) {
// CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
// CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T6]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
Test1 *ptr = test1_helper();
char *pc = ptr.PropertyReturnsInnerPointer;
}

void test1d(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease
Expand All @@ -110,9 +150,13 @@ void test1d(void) {
// CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8*
// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
// CHECK-NEXT: store i8* [[CALL1]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[TEN]])
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
__attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
char *pc = ptr.PropertyReturnsInnerPointer;
Expand Down
12 changes: 12 additions & 0 deletions clang/test/CodeGenObjC/arc-ternary-op.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ void test0(_Bool cond) {
// CHECK-NEXT: [[RELCOND:%.*]] = alloca i1
// CHECK-NEXT: zext
// CHECK-NEXT: store
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load i8, i8* [[COND]]
// CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
// CHECK-NEXT: store i1 false, i1* [[RELCOND]]
Expand All @@ -29,6 +31,8 @@ void test0(_Bool cond) {
// CHECK-NEXT: br label
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
id x = (cond ? 0 : test0_helper());
}
Expand All @@ -49,7 +53,11 @@ void test1(int cond) {
// CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8*
// CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1
// CHECK-NEXT: store i32
// CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKPTR1]])
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)

// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
Expand Down Expand Up @@ -93,6 +101,10 @@ void test1(int cond) {
// CHECK-NEXT: br label

// CHECK: call void @objc_destroyWeak(i8** [[WEAK]])
// CHECK: [[WEAKPTR2:%.*]] = bitcast i8** [[WEAK]] to i8*
// CHECK: call void @llvm.lifetime.end(i64 8, i8* [[WEAKPTR2]])
// CHECK: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
// CHECK: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])
// CHECK: ret void
}

Expand Down
109 changes: 98 additions & 11 deletions clang/test/CodeGenObjC/arc.m

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions clang/test/CodeGenObjC/exceptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ void f3() {
extern void f3_helper(int, int*);

// CHECK: [[X:%.*]] = alloca i32
// CHECK: [[XPTR:%.*]] = bitcast i32* [[X]] to i8*
// CHECK: call void @llvm.lifetime.start(i64 4, i8* [[XPTR]])
// CHECK: store i32 0, i32* [[X]]
int x = 0;

Expand Down Expand Up @@ -122,6 +124,7 @@ void f3() {
}

// CHECK: call void @f3_helper(i32 4, i32* [[X]])
// CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[XPTR]])
// CHECK-NEXT: ret void
f3_helper(4, &x);
}
Expand Down
10 changes: 10 additions & 0 deletions clang/test/CodeGenObjCXX/arc-move.mm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ void library_move(__strong id &x, __strong id &y) {

// CHECK-LABEL: define void @_Z12library_moveRU8__strongP11objc_object
void library_move(__strong id &y) {
// CHECK: [[X:%.*]] = alloca i8*, align 8
// CHECK: [[I:%.*]] = alloca i32, align 4
// CHECK: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
// CHECK: [[Y:%[a-zA-Z0-9]+]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_
// Load the object
// CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[Y]]
Expand All @@ -55,10 +59,16 @@ void library_move(__strong id &y) {
// CHECK-NEXT: store i8* [[OBJ]], i8** [[X:%[a-zA-Z0-9]+]]
id x = move(y);

// CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])
// CHECK-NEXT: store i32 17
int i = 17;
// CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])
// CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[OBJ]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
}

Expand Down
8 changes: 8 additions & 0 deletions clang/test/CodeGenObjCXX/arc-references.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ void test1(__strong id &x, __weak id &y) {

//CHECK: define void @_Z5test3v
void test3() {
// CHECK: [[REF:%.*]] = alloca i8**, align 8
// CHECK: call i8* @objc_initWeak
// CHECK-NEXT: store i8**
const __weak id &ref = strong_id();
// CHECK-NEXT: call void @_Z6calleev()
callee();
// CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR]])
// CHECK-NEXT: call void @objc_destroyWeak
// CHECK-NEXT: ret void
}
Expand All @@ -62,6 +65,7 @@ void test4(__strong id &x) {
// CHECK-LABEL: define void @_Z5test5RU8__strongP11objc_object
void test5(__strong id &x) {
// CHECK: [[REFTMP:%.*]] = alloca {{%.*}}*, align 8
// CHECK: [[I:%.*]] = alloca i32, align 4
// CHECK: [[OBJ_ID:%.*]] = call i8* @objc_retain(
// CHECK-NEXT: [[OBJ_A:%.*]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]*
// CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]]
Expand All @@ -70,8 +74,12 @@ void test5(__strong id &x) {
// CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = load [[A]]*, [[A]]** [[REFTMP]]
// CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8*
// CHECK-NEXT: call void @objc_release
// CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])
// CHECK-NEXT: store i32 17, i32
int i = 17;
// CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])
// CHECK-NEXT: ret void
}

Expand Down
27 changes: 27 additions & 0 deletions clang/test/CodeGenObjCXX/arc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ void test34(int cond) {
// CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8*
// CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1
// CHECK-NEXT: store i32
// CHECK-NEXT: [[STRONGP:%.*]] = bitcast i8** [[STRONG]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGP]])
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: [[WEAKP:%.*]] = bitcast i8** [[WEAK]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKP]])
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)

// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
Expand Down Expand Up @@ -120,56 +124,77 @@ void test34(int cond) {

// CHECK-LABEL: define void @_Z6test3513Test35_HelperPS_
void test35(Test35_Helper x0, Test35_Helper *x0p) {
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject1Ev
// CHECK-NOT: call i8* @objc_retain
id obj1 = Test35_Helper::makeObject1();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev
// CHECK-NOT: call i8* @objc_retain
id obj2 = x0.makeObject2();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev
// CHECK-NOT: call i8* @objc_retain
id obj3 = x0p->makeObject2();
id (Test35_Helper::*pmf)() __attribute__((ns_returns_retained))
= &Test35_Helper::makeObject2;
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
// CHECK-NOT: call i8* @objc_retain
id obj4 = (x0.*pmf)();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
// CHECK-NOT: call i8* @objc_retain
id obj5 = (x0p->*pmf)();

// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

// CHECK-LABEL: define void @_Z7test35b13Test35_HelperPS_
void test35b(Test35_Helper x0, Test35_Helper *x0p) {
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject3Ev
// CHECK: call i8* @objc_retain
id obj1 = Test35_Helper::makeObject3();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev
// CHECK: call i8* @objc_retain
id obj2 = x0.makeObject4();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev
// CHECK: call i8* @objc_retain
id obj3 = x0p->makeObject4();
id (Test35_Helper::*pmf)() = &Test35_Helper::makeObject4;
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
// CHECK: call i8* @objc_retain
id obj4 = (x0.*pmf)();
// CHECK: call void @llvm.lifetime.start
// CHECK: call i8* %
// CHECK: call i8* @objc_retain
id obj5 = (x0p->*pmf)();

// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK: call void @objc_release
// CHECK: call void @llvm.lifetime.end
// CHECK-NEXT: ret void
}

Expand Down Expand Up @@ -290,6 +315,8 @@ + (void) foo:(id *)errorPtr;
// CHECK-LABEL: define weak_odr void @_Z13test40_helperIiEvv()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
// CHECK-NEXT: [[XP:%.*]] = bitcast i8** [[X]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XP]])
// CHECK-NEXT: store i8* null, i8** [[X]]
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]]
Expand Down
10 changes: 10 additions & 0 deletions clang/test/CodeGenObjCXX/literals.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@

// CHECK-LABEL: define void @_Z10test_arrayv
void test_array() {
// CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8*
// CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]

// Initializing first element
// CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]])
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 0
// CHECK-NEXT: call void @_ZN1XC1Ev
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
Expand Down Expand Up @@ -47,6 +50,8 @@ void test_array() {
// CHECK-NEXT: call void @_ZN1XD1Ev
// CHECK-NOT: ret void
// CHECK: call void @objc_release
// CHECK-NEXT: [[PTR2:%.*]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR2]])
// CHECK-NEXT: ret void

// Check cleanups
Expand All @@ -63,9 +68,12 @@ void test_array() {
// CHECK-LABEL: define weak_odr void @_Z24test_array_instantiationIiEvv
template<typename T>
void test_array_instantiation() {
// CHECK: [[ARR:%[a-zA-Z0-9.]+]] = alloca i8*
// CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*]

// Initializing first element
// CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]])
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i32 0, i32 0
// CHECK-NEXT: call void @_ZN1XC1Ev
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
Expand Down Expand Up @@ -94,6 +102,8 @@ void test_array_instantiation() {
// CHECK-NEXT: call void @_ZN1XD1Ev
// CHECK-NOT: ret void
// CHECK: call void @objc_release
// CHECK-NEXT: [[PTR2]] = bitcast i8** [[ARR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR2]])
// CHECK-NEXT: ret void

// Check cleanups
Expand Down