2013-09-04 12:12:25 +08:00
|
|
|
// RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout
|
2013-08-12 20:51:05 +08:00
|
|
|
// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.layout %s
|
2013-01-17 08:25:06 +08:00
|
|
|
// rdar://12752901
|
2010-08-05 07:55:24 +08:00
|
|
|
|
2010-08-06 05:00:25 +08:00
|
|
|
struct S {
|
|
|
|
int i1;
|
|
|
|
id o1;
|
|
|
|
struct V {
|
|
|
|
int i2;
|
|
|
|
id o2;
|
|
|
|
} v1;
|
|
|
|
int i3;
|
|
|
|
id o3;
|
|
|
|
};
|
|
|
|
|
2010-08-05 07:55:24 +08:00
|
|
|
__weak id wid;
|
|
|
|
void x(id y) {}
|
|
|
|
void y(int a) {}
|
|
|
|
|
2022-02-17 05:09:36 +08:00
|
|
|
extern id opaque_id(void);
|
2011-02-07 18:33:21 +08:00
|
|
|
|
2022-02-17 05:09:36 +08:00
|
|
|
void f(void) {
|
2010-08-05 07:55:24 +08:00
|
|
|
__block int byref_int = 0;
|
|
|
|
char ch = 'a';
|
|
|
|
char ch1 = 'b';
|
|
|
|
char ch2 = 'c';
|
|
|
|
short sh = 2;
|
2011-02-07 18:33:21 +08:00
|
|
|
const id bar = (id) opaque_id();
|
2010-08-05 07:55:24 +08:00
|
|
|
id baz = 0;
|
|
|
|
__strong void *strong_void_sta;
|
|
|
|
__block id byref_bab = (id)0;
|
|
|
|
__block void *bl_var1;
|
|
|
|
int i; double dob;
|
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
// The patterns here are a sequence of bytes, each saying first how
|
|
|
|
// many sizeof(void*) chunks to skip (high nibble) and then how many
|
|
|
|
// to scan (low nibble). A zero byte says that we've reached the end
|
|
|
|
// of the pattern.
|
|
|
|
//
|
|
|
|
// All of these patterns start with 01 3x because the block header on
|
|
|
|
// LP64 consists of an isa pointer (which we're supposed to scan for
|
|
|
|
// some reason) followed by three words (2 ints, a function pointer,
|
|
|
|
// and a descriptor pointer).
|
|
|
|
|
|
|
|
// FIXME: do these really have to be named L_OBJC_CLASS_NAME_xxx?
|
|
|
|
// FIXME: sequences should never end in x0 00 instead of just 00
|
|
|
|
|
|
|
|
// Test 1
|
|
|
|
// byref int, short, char, char, char, id, id, strong void*, byref id
|
2013-01-17 08:25:06 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x10, 0x00
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^b)(void) = ^{
|
2010-08-05 07:55:24 +08:00
|
|
|
byref_int = sh + ch+ch1+ch2 ;
|
|
|
|
x(bar);
|
|
|
|
x(baz);
|
|
|
|
x((id)strong_void_sta);
|
|
|
|
x(byref_bab);
|
|
|
|
};
|
|
|
|
b();
|
|
|
|
|
|
|
|
// Test 2
|
2011-02-07 18:33:21 +08:00
|
|
|
// byref int, short, char, char, char, id, id, strong void*, byref void*, byref id
|
|
|
|
// 01 36 10 00
|
2013-01-17 08:25:06 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x36, 0x10, 0x00
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^c)(void) = ^{
|
2010-08-05 07:55:24 +08:00
|
|
|
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
|
2011-02-07 18:33:21 +08:00
|
|
|
// byref int, short, char, char, char, id, id, byref void*, int, double, byref id
|
|
|
|
// 01 34 11 30 00
|
|
|
|
// FIXME: we'd get a better format here if we sorted by scannability, not just alignment
|
2013-01-17 08:25:06 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x35, 0x30, 0x00
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^d)(void) = ^{
|
2010-08-05 07:55:24 +08:00
|
|
|
byref_int = sh + ch+ch1+ch2 ;
|
|
|
|
x(bar);
|
|
|
|
x(baz);
|
|
|
|
x(wid);
|
|
|
|
bl_var1 = 0;
|
|
|
|
y(i + dob);
|
|
|
|
x(byref_bab);
|
|
|
|
};
|
|
|
|
d();
|
2010-08-06 05:00:25 +08:00
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
// Test 4
|
|
|
|
// struct S (int, id, int, id, int, id)
|
2012-11-06 11:38:02 +08:00
|
|
|
// 01 41 11 11 00
|
2013-01-17 08:25:06 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x11, 0x00
|
2010-08-06 05:00:25 +08:00
|
|
|
struct S s2;
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^e)(void) = ^{
|
2010-08-06 05:00:25 +08:00
|
|
|
x(s2.o1);
|
|
|
|
};
|
|
|
|
e();
|
2010-08-05 07:55:24 +08:00
|
|
|
}
|
|
|
|
|
2010-08-07 00:28:55 +08:00
|
|
|
// Test 5 (unions/structs and their nesting):
|
2022-02-17 05:09:36 +08:00
|
|
|
void Test5(void) {
|
2011-02-07 18:33:21 +08:00
|
|
|
struct S5 {
|
2010-08-07 00:28:55 +08:00
|
|
|
int i1;
|
|
|
|
id o1;
|
|
|
|
struct V {
|
|
|
|
int i2;
|
|
|
|
id o2;
|
|
|
|
} v1;
|
|
|
|
int i3;
|
|
|
|
union UI {
|
|
|
|
void * i1;
|
|
|
|
id o1;
|
|
|
|
int i3;
|
|
|
|
id o3;
|
|
|
|
}ui;
|
2011-02-07 18:33:21 +08:00
|
|
|
};
|
2010-08-07 00:28:55 +08:00
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
union U {
|
2010-08-07 00:28:55 +08:00
|
|
|
void * i1;
|
|
|
|
id o1;
|
|
|
|
int i3;
|
|
|
|
id o3;
|
2011-02-07 18:33:21 +08:00
|
|
|
}ui;
|
2010-08-07 00:28:55 +08:00
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
struct S5 s2;
|
|
|
|
union U u2;
|
|
|
|
|
|
|
|
// struct s2 (int, id, int, id, int, id?), union u2 (id?)
|
2012-11-06 11:38:02 +08:00
|
|
|
// 01 41 11 12 00
|
2013-01-17 08:25:06 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x41, 0x11, 0x12, 0x00
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^c)(void) = ^{
|
2010-08-07 00:28:55 +08:00
|
|
|
x(s2.ui.o1);
|
|
|
|
x(u2.o1);
|
2011-02-07 18:33:21 +08:00
|
|
|
};
|
|
|
|
c();
|
2010-08-07 00:28:55 +08:00
|
|
|
}
|
|
|
|
|
2010-09-11 09:27:29 +08:00
|
|
|
// rdar: //8417746
|
|
|
|
void CFRelease(id);
|
|
|
|
void notifyBlock(id dependentBlock) {
|
|
|
|
id singleObservationToken;
|
|
|
|
id token;
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^b)(void);
|
2011-02-07 18:33:21 +08:00
|
|
|
|
2022-02-17 05:09:36 +08:00
|
|
|
// id, id, void(^)(void)
|
2011-02-07 18:33:21 +08:00
|
|
|
// 01 33 00
|
2013-01-17 08:25:06 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x33, 0x00
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^wrapperBlock)(void) = ^(void) {
|
2010-09-11 09:27:29 +08:00
|
|
|
CFRelease(singleObservationToken);
|
|
|
|
CFRelease(singleObservationToken);
|
|
|
|
CFRelease(token);
|
|
|
|
CFRelease(singleObservationToken);
|
|
|
|
b();
|
|
|
|
};
|
|
|
|
wrapperBlock();
|
|
|
|
}
|
|
|
|
|
2022-02-17 05:09:36 +08:00
|
|
|
void test_empty_block(void) {
|
2011-02-07 18:33:21 +08:00
|
|
|
// 01 00
|
Fix and stylize the emission of GC/ARC ivar and GC block layout strings.
Specifically, handle under-aligned object references (by explicitly
ignoring them, because this just isn't representable in the format;
yes, this means that GC silently ignores such references), descend
into anonymous structs and unions, stop classifying fields of
pointer-to-strong/weak type as strong/weak in ARC mode, and emit
skips to cover the entirety of block layouts in GC mode. As a
cleanup, extract this code into a helper class, avoid a number of
unnecessary copies and layout queries, generate skips implicitly
instead of explicitly tracking them, and clarify the bitmap-creation
logic.
llvm-svn: 250919
2015-10-22 02:06:47 +08:00
|
|
|
// CHECK-LP64: block variable layout for block: 0x01, 0x30, 0x00
|
2022-02-17 05:09:36 +08:00
|
|
|
void (^wrapperBlock)(void) = ^(void) {
|
2011-02-07 18:33:21 +08:00
|
|
|
};
|
2010-09-14 00:09:44 +08:00
|
|
|
wrapperBlock();
|
|
|
|
}
|
2014-02-25 03:10:37 +08:00
|
|
|
|
|
|
|
// rdar://16111839
|
|
|
|
typedef union { char ch[8]; } SS;
|
|
|
|
typedef struct { SS s[4]; } CS;
|
2022-02-17 05:09:36 +08:00
|
|
|
void test_union_in_layout(void) {
|
2014-02-25 03:10:37 +08:00
|
|
|
CS cs;
|
|
|
|
^{ cs; };
|
|
|
|
}
|