1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X64 2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -fblocks -triple i686-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X32 3*f4a2713aSLionel Sambuc 4*f4a2713aSLionel Sambuc // X64: internal constant {{.*}} { i8** @_NSConcreteGlobalBlock, i32 1879048192 5*f4a2713aSLionel Sambuc // X64: store i32 1610612736, i32* %want 6*f4a2713aSLionel Sambuc 7*f4a2713aSLionel Sambuc // X32: @_NSConcreteGlobalBlock, i32 1879048192, i32 0, 8*f4a2713aSLionel Sambuc // X32: store i32 1610612736, i32* %want 9*f4a2713aSLionel Sambuc 10*f4a2713aSLionel Sambuc // rdar://7677537 11*f4a2713aSLionel Sambuc int printf(const char *, ...); 12*f4a2713aSLionel Sambuc void *malloc(__SIZE_TYPE__ size); 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc typedef struct bigbig { 15*f4a2713aSLionel Sambuc int array[512]; 16*f4a2713aSLionel Sambuc char more[32]; 17*f4a2713aSLionel Sambuc } BigStruct_t; 18*f4a2713aSLionel Sambuc 19*f4a2713aSLionel Sambuc BigStruct_t (^global)(void) = ^{ return *(BigStruct_t *)malloc(sizeof(struct bigbig)); }; 20*f4a2713aSLionel Sambuc 21*f4a2713aSLionel Sambuc const char * getBlockSignature(void *); 22*f4a2713aSLionel Sambuc 23*f4a2713aSLionel Sambuc BigStruct_t foo(int param) { 24*f4a2713aSLionel Sambuc BigStruct_t x; 25*f4a2713aSLionel Sambuc BigStruct_t (^f)(int) = ^(int param) { 26*f4a2713aSLionel Sambuc BigStruct_t *result = malloc(sizeof(BigStruct_t)); 27*f4a2713aSLionel Sambuc result->array[23] = param; 28*f4a2713aSLionel Sambuc return *result; 29*f4a2713aSLionel Sambuc }; 30*f4a2713aSLionel Sambuc getBlockSignature(f); 31*f4a2713aSLionel Sambuc return x; 32*f4a2713aSLionel Sambuc } 33*f4a2713aSLionel Sambuc 34*f4a2713aSLionel Sambuc enum { 35*f4a2713aSLionel Sambuc BLOCK_HAS_COPY_DISPOSE = (1 << 25), 36*f4a2713aSLionel Sambuc BLOCK_HAS_CXX_OBJ = (1 << 26), 37*f4a2713aSLionel Sambuc BLOCK_IS_GLOBAL = (1 << 28), 38*f4a2713aSLionel Sambuc BLOCK_USE_STRET = (1 << 29), 39*f4a2713aSLionel Sambuc BLOCK_HAS_OBJC_TYPE = (1 << 30) 40*f4a2713aSLionel Sambuc }; 41*f4a2713aSLionel Sambuc 42*f4a2713aSLionel Sambuc struct block_descriptor_big { 43*f4a2713aSLionel Sambuc unsigned long int reserved; 44*f4a2713aSLionel Sambuc unsigned long int size; 45*f4a2713aSLionel Sambuc void (*copy)(void *dst, void *src); // conditional on BLOCK_HAS_COPY_DISPOSE 46*f4a2713aSLionel Sambuc void (*dispose)(void *); // conditional on BLOCK_HAS_COPY_DISPOSE 47*f4a2713aSLionel Sambuc const char *signature; // conditional on BLOCK_HAS_OBJC 48*f4a2713aSLionel Sambuc const char *layout; // conditional on BLOCK_HAS_OBJC 49*f4a2713aSLionel Sambuc }; 50*f4a2713aSLionel Sambuc struct block_descriptor_small { 51*f4a2713aSLionel Sambuc unsigned long int reserved; 52*f4a2713aSLionel Sambuc unsigned long int size; 53*f4a2713aSLionel Sambuc const char *signature; // conditional on BLOCK_HAS_OBJC 54*f4a2713aSLionel Sambuc const char *layout; // conditional on BLOCK_HAS_OBJC 55*f4a2713aSLionel Sambuc }; 56*f4a2713aSLionel Sambuc 57*f4a2713aSLionel Sambuc struct block_layout_abi { // can't change 58*f4a2713aSLionel Sambuc void *isa; 59*f4a2713aSLionel Sambuc int flags; 60*f4a2713aSLionel Sambuc int reserved; 61*f4a2713aSLionel Sambuc void (*invoke)(void *, ...); 62*f4a2713aSLionel Sambuc struct block_descriptor_big *descriptor; 63*f4a2713aSLionel Sambuc }; 64*f4a2713aSLionel Sambuc 65*f4a2713aSLionel Sambuc const char *getBlockSignature(void *block) { 66*f4a2713aSLionel Sambuc struct block_layout_abi *layout = (struct block_layout_abi *)block; 67*f4a2713aSLionel Sambuc if ((layout->flags & BLOCK_HAS_OBJC_TYPE) != BLOCK_HAS_OBJC_TYPE) return 0; 68*f4a2713aSLionel Sambuc if (layout->flags & BLOCK_HAS_COPY_DISPOSE) 69*f4a2713aSLionel Sambuc return layout->descriptor->signature; 70*f4a2713aSLionel Sambuc else 71*f4a2713aSLionel Sambuc return ((struct block_descriptor_small *)layout->descriptor)->signature; 72*f4a2713aSLionel Sambuc } 73*f4a2713aSLionel Sambuc 74*f4a2713aSLionel Sambuc int usesStruct(void *block) { 75*f4a2713aSLionel Sambuc struct block_layout_abi *layout = (struct block_layout_abi *)block; 76*f4a2713aSLionel Sambuc int want = BLOCK_HAS_OBJC_TYPE | BLOCK_USE_STRET; 77*f4a2713aSLionel Sambuc return (layout->flags & want) == want; 78*f4a2713aSLionel Sambuc } 79*f4a2713aSLionel Sambuc 80*f4a2713aSLionel Sambuc 81*f4a2713aSLionel Sambuc int main(int argc, char *argv[]) { 82*f4a2713aSLionel Sambuc printf("desired global flags: %d\n", BLOCK_USE_STRET | BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE); 83*f4a2713aSLionel Sambuc printf("desired stack flags: %d\n", BLOCK_USE_STRET | BLOCK_HAS_OBJC_TYPE); 84*f4a2713aSLionel Sambuc 85*f4a2713aSLionel Sambuc printf("should be non-zero: %d\n", usesStruct(global)); 86*f4a2713aSLionel Sambuc BigStruct_t x; 87*f4a2713aSLionel Sambuc BigStruct_t (^local)(int) = ^(int param) { 88*f4a2713aSLionel Sambuc BigStruct_t *result = (BigStruct_t *)malloc(sizeof(BigStruct_t)); 89*f4a2713aSLionel Sambuc result->array[23] = argc; 90*f4a2713aSLionel Sambuc return *result; 91*f4a2713aSLionel Sambuc }; 92*f4a2713aSLionel Sambuc printf("should be non-zero: %d\n", usesStruct(global)); 93*f4a2713aSLionel Sambuc printf("should be non-zero: %d\n", usesStruct(local)); 94*f4a2713aSLionel Sambuc printf("should be zero: %d\n", usesStruct(^void(int x){ })); 95*f4a2713aSLionel Sambuc return 0; 96*f4a2713aSLionel Sambuc } 97*f4a2713aSLionel Sambuc 98*f4a2713aSLionel Sambuc /* 99*f4a2713aSLionel Sambuc desired global flags: 1879048192 100*f4a2713aSLionel Sambuc desired stack flags: 1610612736 101*f4a2713aSLionel Sambuc should be non-zero: 1 102*f4a2713aSLionel Sambuc should be non-zero: 1 103*f4a2713aSLionel Sambuc should be non-zero: 1 104*f4a2713aSLionel Sambuc should be zero: 0 105*f4a2713aSLionel Sambuc 106*f4a2713aSLionel Sambuc */ 107