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