diff options
Diffstat (limited to 'test/CodeGenObjC')
-rw-r--r-- | test/CodeGenObjC/bitfield-access.m | 43 | ||||
-rw-r--r-- | test/CodeGenObjC/block-var-layout.m | 123 | ||||
-rw-r--r-- | test/CodeGenObjC/debug-info-linkagename.m | 3 | ||||
-rw-r--r-- | test/CodeGenObjC/exceptions.m | 102 | ||||
-rw-r--r-- | test/CodeGenObjC/for-in.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/fpret.m | 38 | ||||
-rw-r--r-- | test/CodeGenObjC/gnu-exceptions.m | 29 | ||||
-rw-r--r-- | test/CodeGenObjC/ivar-layout-nonfragile-abi2.m | 51 | ||||
-rw-r--r-- | test/CodeGenObjC/property-dbg.m | 2 | ||||
-rw-r--r-- | test/CodeGenObjC/return-objc-object.mm | 19 | ||||
-rw-r--r-- | test/CodeGenObjC/super-dotsyntax-struct-property.m | 47 | ||||
-rw-r--r-- | test/CodeGenObjC/synchronized.m | 56 | ||||
-rw-r--r-- | test/CodeGenObjC/unwind-fn.m | 2 | ||||
-rw-r--r-- | test/CodeGenObjC/x86_64-struct-return-gc.m | 2 |
14 files changed, 503 insertions, 18 deletions
diff --git a/test/CodeGenObjC/bitfield-access.m b/test/CodeGenObjC/bitfield-access.m new file mode 100644 index 0000000..16b0001 --- /dev/null +++ b/test/CodeGenObjC/bitfield-access.m @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -o %t %s +// RUN: FileCheck -check-prefix=CHECK-I386 < %t %s +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -emit-llvm -o %t %s +// RUN: FileCheck -check-prefix=CHECK-ARM < %t %s + +@interface I0 { +@public + unsigned x:15; + unsigned y: 1; +} +@end + +// Check that we don't try to use an i32 load here, which would reach beyond the +// end of the structure. +// +// CHECK-I386: define i32 @f0( +// CHECK-I386: [[t0_0:%.*]] = load i16* {{.*}}, align 1 +// CHECK-I386: lshr i16 [[t0_0]], 7 +// CHECK-I386: } +int f0(I0 *a) { + return a->y; +} + +// Check that we can handled straddled loads. +// +// CHECK-ARM: define i32 @f1( +// CHECK-ARM: [[t1_ptr:%.*]] = getelementptr +// CHECK-ARM: [[t1_base:%.*]] = bitcast i8* [[t1_ptr]] to i32* +// CHECK-ARM: [[t1_0:%.*]] = load i32* [[t1_base]], align 1 +// CHECK-ARM: lshr i32 [[t1_0]], 1 +// CHECK-ARM: [[t1_base_2_cast:%.*]] = bitcast i32* %{{.*}} to i8* +// CHECK-ARM: [[t1_base_2:%.*]] = getelementptr i8* [[t1_base_2_cast]] +// CHECK-ARM: [[t1_1:%.*]] = load i8* [[t1_base_2]], align 1 +// CHECK-ARM: and i8 [[t1_1:%.*]], 1 +// CHECK-ARM: } +@interface I1 { +@public + unsigned x: 1; + unsigned y:32; +} +@end + +int f1(I1 *a) { return a->y; } diff --git a/test/CodeGenObjC/block-var-layout.m b/test/CodeGenObjC/block-var-layout.m new file mode 100644 index 0000000..bf9ba8d --- /dev/null +++ b/test/CodeGenObjC/block-var-layout.m @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -O0 -S %s -o %t-64.s +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s + +struct S { + int i1; + id o1; + struct V { + int i2; + id o2; + } v1; + int i3; + id o3; +}; + +__weak id wid; +void x(id y) {} +void y(int a) {} + +void f() { + __block int byref_int = 0; + char ch = 'a'; + char ch1 = 'b'; + char ch2 = 'c'; + short sh = 2; + const id bar = (id)0; + id baz = 0; + __strong void *strong_void_sta; + __block id byref_bab = (id)0; + __block void *bl_var1; + int i; double dob; + + void (^b)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + b(); + +// Test 2 + void (^c)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; + c(); + +// Test 3 +void (^d)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x(wid); + bl_var1 = 0; + y(i + dob); + x(byref_bab); + }; + d(); + +// Test4 + struct S s2; + void (^e)() = ^{ + x(s2.o1); + }; + e(); +} + +// Test 5 (unions/structs and their nesting): +void Test5() { +struct S5 { + int i1; + id o1; + struct V { + int i2; + id o2; + } v1; + int i3; + union UI { + void * i1; + id o1; + int i3; + id o3; + }ui; +}; + +union U { + void * i1; + id o1; + int i3; + id o3; +}ui; + +struct S5 s2; +union U u2; +void (^c)() = ^{ + x(s2.ui.o1); + x(u2.o1); +}; +c(); + +} + +// CHECK-LP64: L_OBJC_CLASS_NAME_: +// CHECK-LP64-NEXT: .asciz "A\024" + +// CHECK-LP64: L_OBJC_CLASS_NAME_1: +// CHECK-LP64-NEXT: .asciz "A\025" + +// CHECK-LP64: L_OBJC_CLASS_NAME_6: +// CHECK-LP64-NEXT: .asciz "A\023!" + +// CHECK-LP64: L_OBJC_CLASS_NAME_11: +// CHECK-LP64-NEXT: .asciz "Q\021\021" + +// CHECK-LP64: L_OBJC_CLASS_NAME_14: +// CHECK-LP64-NEXT: .asciz "Q\021\022p" diff --git a/test/CodeGenObjC/debug-info-linkagename.m b/test/CodeGenObjC/debug-info-linkagename.m index 2b10e2b..b606e5d 100644 --- a/test/CodeGenObjC/debug-info-linkagename.m +++ b/test/CodeGenObjC/debug-info-linkagename.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -g -S -o %t %s -// RUN: not grep 001 %t +// RUN: not grep "001-[F bar" %t +// Linkage name should not use 001 prefix in debug info. @interface F -(int) bar; diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m index 5be6959..b431e37 100644 --- a/test/CodeGenObjC/exceptions.m +++ b/test/CodeGenObjC/exceptions.m @@ -25,15 +25,111 @@ void f1() { // CHECK-NEXT: icmp // CHECK-NEXT: br i1 @try { - // CHECK: call void @foo() + // CHECK: call void asm sideeffect "", "*m" + // CHECK-NEXT: call void @foo() foo(); - // CHECK: call void @objc_exception_try_exit + // CHECK-NEXT: call void @objc_exception_try_exit // CHECK-NEXT: ret void - // CHECK: call i8* @objc_exception_extract + // CHECK: call void asm sideeffect "", "=*m" // CHECK-NEXT: ret void } @finally { break; } } } + +// Test that modifications to local variables are respected under +// optimization. rdar://problem/8160285 + +// CHECK: define i32 @f2() +int f2() { + extern void foo(void); + + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 5, i32* [[X]] + int x = 0; + x += 5; + + // CHECK: [[SETJMP:%.*]] = call i32 @_setjmp + // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0 + // CHECK-NEXT: br i1 [[CAUGHT]] + @try { + // If the optimizers ever figure out how to make this store 6, + // that's okay. + // CHECK: [[T1:%.*]] = load i32* [[X]] + // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1 + // CHECK-NEXT: store i32 [[T2]], i32* [[X]] + x++; + // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]] + // CHECK-NEXT: call void @foo() + // CHECK-NEXT: call void @objc_exception_try_exit + // CHECK-NEXT: [[T:%.*]] = load i32* [[X]] + // CHECK-NEXT: ret i32 [[T]] + foo(); + } @catch (id) { + // Landing pad. Note that we elide the re-enter. + // CHECK: call void asm sideeffect "", "=*m,=*m"(i32* [[X]] + // CHECK-NEXT: call i8* @objc_exception_extract + // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]] + // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1 + + // This store is dead. + // CHECK-NEXT: store i32 [[T2]], i32* [[X]] + + // CHECK-NEXT: ret i32 [[T2]] + x--; + } + return x; +} + +// Test that the cleanup destination is saved when entering a finally +// block. rdar://problem/8293901 +// CHECK: define void @f3() +void f3() { + extern void f3_helper(int, int*); + + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 0, i32* [[X]] + int x = 0; + + // CHECK: call void @objc_exception_try_enter( + // CHECK: call i32 @_setjmp + // CHECK-NEXT: icmp eq + // CHECK-NEXT: br i1 + + @try { + // CHECK: call void @f3_helper(i32 0, i32* [[X]]) + // CHECK: call void @objc_exception_try_exit( + f3_helper(0, &x); + } @finally { + // CHECK: [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ] + // CHECK: call void @objc_exception_try_enter + // CHECK: call i32 @_setjmp + @try { + // CHECK: call void @f3_helper(i32 1, i32* [[X]]) + // CHECK: call void @objc_exception_try_exit( + f3_helper(1, &x); + } @finally { + // CHECK: [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ] + // CHECK: call void @f3_helper(i32 2, i32* [[X]]) + f3_helper(2, &x); + + // This loop is large enough to dissuade the optimizer from just + // duplicating the finally block. + while (x) f3_helper(3, &x); + + // This is a switch or maybe some chained branches, but relying + // on a specific result from the optimizer is really unstable. + // CHECK: [[DEST2]] + } + + // This is a switch or maybe some chained branches, but relying + // on a specific result from the optimizer is really unstable. + // CHECK: [[DEST1]] + } + + // CHECK: call void @f3_helper(i32 4, i32* [[X]]) + // CHECK-NEXT: ret void + f3_helper(4, &x); +} diff --git a/test/CodeGenObjC/for-in.m b/test/CodeGenObjC/for-in.m index 354ff32..7e6098a 100644 --- a/test/CodeGenObjC/for-in.m +++ b/test/CodeGenObjC/for-in.m @@ -23,7 +23,7 @@ void t0() { p("array.length: %d\n", [array count]); unsigned index = 0; - for (NSString *i in array) { + for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} p("element %d: %s\n", index++, [i cString]); } } @@ -33,7 +33,7 @@ void t1() { p("array.length: %d\n", [array count]); unsigned index = 0; - for (NSString *i in array) { + for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} index++; if (index == 10) continue; diff --git a/test/CodeGenObjC/fpret.m b/test/CodeGenObjC/fpret.m new file mode 100644 index 0000000..4884888 --- /dev/null +++ b/test/CodeGenObjC/fpret.m @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-X86_32 %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-X86_64 %s +// +// RUN: %clang_cc1 -triple armv7-apple-darwin10 -emit-llvm -target-abi apcs-gnu -o - %s | \ +// RUN: FileCheck --check-prefix=CHECK-ARMV7 %s + +@interface A +-(float) floatValue; +-(double) doubleValue; +-(long double) longDoubleValue; +@end + + +// CHECK-X86_32: define void @t0() +// CHECK-X86_32: call float bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_32: call double {{.*}} @objc_msgSend_fpret( +// CHECK-X86_32: call x86_fp80 bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_32: } +// +// CHECK-X86_64: define void @t0() +// CHECK-X86_64: call float bitcast {{.*}} @objc_msgSend to +// CHECK-X86_64: call double bitcast {{.*}} @objc_msgSend to +// CHECK-X86_64: call x86_fp80 bitcast {{.*}} @objc_msgSend_fpret to +// CHECK-X86_64: } +// +// CHECK-ARMV7: define void @t0() +// CHECK-ARMV7: call float bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: call double bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: call double bitcast {{.*}} @objc_msgSend to +// CHECK-ARMV7: } +void t0() { + [(A*)0 floatValue]; + [(A*)0 doubleValue]; + [(A*)0 longDoubleValue]; +} diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m new file mode 100644 index 0000000..6790a29 --- /dev/null +++ b/test/CodeGenObjC/gnu-exceptions.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fgnu-runtime -o - %s | FileCheck %s + +void opaque(void); +void log(int i); + +@class C; + +// CHECK: define void @test0() { +void test0() { + @try { + // CHECK: invoke void @opaque() + opaque(); + + // CHECK: call void @log(i32 1) + + } @catch (C *c) { + // CHECK: call i8* @llvm.eh.exception() + // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gnu_objc_personality_v0 + // CHECK: br i1 + + // CHECK: call void @log(i32 0) + + // CHECK: call void @objc_exception_throw + + log(0); + } + + log(1); +} diff --git a/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m new file mode 100644 index 0000000..b474caa --- /dev/null +++ b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s +// rdar: // 7824380 + +@interface Super { + int ivar_super_a : 5; +} +@end + +@interface A : Super { +@public + int ivar_a : 5; +} +@end + +int f0(A *a) { + return a->ivar_a; +} + +@interface A () { +@public + int ivar_ext_a : 5; + int ivar_ext_b : 5; +}@end + +int f1(A *a) { + return a->ivar_ext_a + a->ivar_a; +} + +@interface A () { +@public + int ivar_ext2_a : 5; + int ivar_ext2_b : 5; +}@end + +int f2(A* a) { + return a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a; +} + +@implementation A { +@public + int ivar_b : 5; + int ivar_c : 5; + int ivar_d : 5; +} +@end + +int f3(A *a) { + return a->ivar_d + a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a; +} + diff --git a/test/CodeGenObjC/property-dbg.m b/test/CodeGenObjC/property-dbg.m index 5bbb046..42ab611 100644 --- a/test/CodeGenObjC/property-dbg.m +++ b/test/CodeGenObjC/property-dbg.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -S -g -masm-verbose -x objective-c < %s | grep setI | grep DW_AT_name +// RUN: %clang_cc1 -S -g -masm-verbose -x objective-c < %s | grep DW_AT_name @interface Foo { int i; } diff --git a/test/CodeGenObjC/return-objc-object.mm b/test/CodeGenObjC/return-objc-object.mm new file mode 100644 index 0000000..95cce23 --- /dev/null +++ b/test/CodeGenObjC/return-objc-object.mm @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | FileCheck %s + +@protocol P1 @end +@interface NSOperationQueue +{ + char ch[64]; + double d; +} +@end + +NSOperationQueue &f(); +NSOperationQueue<P1> &f1(); + +void call_once() { + f(); + f1(); +} +// CHECK: call %0* @_Z1fv() +// CHECK: call %0* @_Z2f1v() diff --git a/test/CodeGenObjC/super-dotsyntax-struct-property.m b/test/CodeGenObjC/super-dotsyntax-struct-property.m new file mode 100644 index 0000000..aac4c1d --- /dev/null +++ b/test/CodeGenObjC/super-dotsyntax-struct-property.m @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm %s -o - | FileCheck %s +// rdar: // 8203426 + + +typedef double CGFloat; +struct CGPoint { + CGFloat x; + CGFloat y; +}; +typedef struct CGPoint CGPoint; + + + +struct CGSize { + CGFloat width; + CGFloat height; +}; +typedef struct CGSize CGSize; + + +struct CGRect { + CGPoint origin; + CGSize size; +}; +typedef struct CGRect CGRect; + +@interface UIView { +} +@property CGRect frame; +@end + +@interface crashclass : UIView { + +} + +@end + +@implementation crashclass +- (void)setFrame:(CGRect)frame +{ + super.frame = frame; + [super setFrame:frame]; +} + +@end +// CHECK-NOT: declare void @objc_msgSendSuper2_stret +// CHECK: declare i8* @objc_msgSendSuper2 diff --git a/test/CodeGenObjC/synchronized.m b/test/CodeGenObjC/synchronized.m index 1af8234..2a80906 100644 --- a/test/CodeGenObjC/synchronized.m +++ b/test/CodeGenObjC/synchronized.m @@ -1,6 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -triple=i686-apple-darwin9 -o %t %s -O2 -// RUN: grep 'ret i32' %t | count 1 -// RUN: grep 'ret i32 1' %t | count 1 +// RUN: %clang_cc1 -emit-llvm -triple=i686-apple-darwin9 -o - %s -O2 | FileCheck %s @interface MyClass { @@ -10,31 +8,71 @@ @implementation MyClass +// CHECK: define internal void @"\01-[MyClass method]" - (void)method { - @synchronized(self) - { - } + // CHECK: call void @objc_sync_enter + // CHECK: call void @objc_exception_try_enter + // CHECK: call i32 @_setjmp + @synchronized(self) { + } } @end +// CHECK: define void @foo( void foo(id a) { + // CHECK: [[A:%.*]] = alloca i8* + // CHECK: [[SYNC:%.*]] = alloca i8* + + // CHECK: store i8* [[AVAL:%.*]], i8** [[A]] + // CHECK-NEXT: call void @objc_sync_enter(i8* [[AVAL]]) + // CHECK-NEXT: store i8* [[AVAL]], i8** [[SYNC]] + // CHECK-NEXT: call void @objc_exception_try_enter + // CHECK: call i32 @_setjmp @synchronized(a) { + // This is unreachable, but the optimizers can't know that. + // CHECK: call void asm sideeffect "", "=*m,=*m,=*m"(i8** [[A]], i8** [[SYNC]] + // CHECK: call void @objc_sync_exit + // CHECK: call i8* @objc_exception_extract + // CHECK: call void @objc_exception_throw + // CHECK: unreachable + + // CHECK: call void @objc_exception_try_exit + // CHECK: [[T:%.*]] = load i8** [[SYNC]] + // CHECK-NEXT: call void @objc_sync_exit + // CHECK: ret void return; } + } +// CHECK: define i32 @f0( int f0(id a) { + // TODO: we can optimize the ret to a constant if we can figure out + // either that x isn't stored to within the synchronized block or + // that the synchronized block can't longjmp. + + // CHECK: [[X:%.*]] = alloca i32 + // CHECK: store i32 1, i32* [[X]] int x = 0; @synchronized((x++, a)) { } - return x; // ret i32 1 + + // CHECK: [[T:%.*]] = load i32* [[X]] + // CHECK: ret i32 [[T]] + return x; } +// CHECK: define void @f1( void f1(id a) { - // The trick here is that the return shouldn't go through clean up, - // but there isn't a simple way to check this property. + // Check that the return doesn't go through the cleanup. + extern void opaque(void); + opaque(); + + // CHECK: call void @opaque() + // CHECK-NEXT: ret void + @synchronized(({ return; }), a) { return; } diff --git a/test/CodeGenObjC/unwind-fn.m b/test/CodeGenObjC/unwind-fn.m index 48217f0..5bfc7dc 100644 --- a/test/CodeGenObjC/unwind-fn.m +++ b/test/CodeGenObjC/unwind-fn.m @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -fsjlj-exceptions -fobjc-nonfragile-abi -fexceptions -emit-llvm -o - %s | FileCheck --check-prefix=SJLJ_EH %s // DEFAULT_EH: declare void @_Unwind_Resume_or_Rethrow(i8*) -// SJLJ_EH: declare void @_Unwind_SjLj_Resume(i8*) +// SJLJ_EH: declare void @_Unwind_SjLj_Resume_or_Rethrow(i8*) void f1(), f2(); void f0() { diff --git a/test/CodeGenObjC/x86_64-struct-return-gc.m b/test/CodeGenObjC/x86_64-struct-return-gc.m index c62a33f..8022d59 100644 --- a/test/CodeGenObjC/x86_64-struct-return-gc.m +++ b/test/CodeGenObjC/x86_64-struct-return-gc.m @@ -9,7 +9,7 @@ struct Coerce coerce_func(void); void Coerce_test(void) { struct Coerce c; - // CHECK: call i64 @coerce_func + // CHECK: call i8* @coerce_func // CHECK: call i8* @objc_memmove_collectable( c = coerce_func(); } |