Home | History | Annotate | Download | only in CodeGenObjC
      1 // RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout
      2 // RUN: FileCheck --input-file=%t-32.layout %s
      3 // rdar://12184410
      4 // rdar://12752901
      5 
      6 void x(id y) {}
      7 void y(int a) {}
      8 
      9 extern id opaque_id();
     10 
     11 void f() {
     12     __weak id wid;
     13     __block int byref_int = 0;
     14     char ch = 'a';
     15     char ch1 = 'b';
     16     char ch2 = 'c';
     17     short sh = 2;
     18     const id bar = (id) opaque_id();
     19     id baz = 0;
     20     __strong id strong_void_sta;
     21     __block id byref_bab = (id)0;
     22     __block id bl_var1;
     23     int i; double dob;
     24 
     25 // The patterns here are a sequence of bytes, each saying first how
     26 // many sizeof(void*) chunks to skip (high nibble) and then how many
     27 // to scan (low nibble).  A zero byte says that we've reached the end
     28 // of the pattern.
     29 //
     30 // All of these patterns start with 01 3x because the block header on
     31 // LP64 consists of an isa pointer (which we're supposed to scan for
     32 // some reason) followed by three words (2 ints, a function pointer,
     33 // and a descriptor pointer).
     34 
     35 // Test 1
     36 // CHECK: Inline instruction for block variable layout: 0x0320
     37     void (^b)() = ^{
     38         byref_int = sh + ch+ch1+ch2 ;
     39         x(bar);
     40         x(baz);
     41         x((id)strong_void_sta);
     42         x(byref_bab);
     43     };    
     44     b();
     45 
     46 // Test 2
     47 // CHECK: Inline instruction for block variable layout: 0x0331
     48     void (^c)() = ^{
     49         byref_int = sh + ch+ch1+ch2 ;
     50         x(bar);
     51         x(baz);
     52         x((id)strong_void_sta);
     53         x(wid);
     54         bl_var1 = 0;
     55         x(byref_bab);
     56     };    
     57 }
     58 
     59 @class NSString, NSNumber;
     60 void g() {
     61   NSString *foo;
     62    NSNumber *bar;
     63    unsigned int bletch;
     64    __weak id weak_delegate;
     65   unsigned int i;
     66   NSString *y;
     67   NSString *z;
     68 // CHECK: Inline instruction for block variable layout: 0x0401
     69   void (^c)() = ^{
     70    int j = i + bletch;
     71    x(foo);
     72    x(bar);
     73    x(weak_delegate);
     74    x(y);
     75    x(z); 
     76   };
     77   c();
     78 }
     79 
     80 // Test 5 (unions/structs and their nesting):
     81 void h() {
     82   struct S5 {
     83     int i1;
     84     __unsafe_unretained id o1;
     85     struct V {
     86      int i2;
     87      __unsafe_unretained id o2;
     88     } v1;
     89     int i3;
     90     union UI {
     91         void * i1;
     92         __unsafe_unretained id o1;
     93         int i3;
     94         __unsafe_unretained id o3;
     95     }ui;
     96   };
     97 
     98   union U {
     99         void * i1;
    100         __unsafe_unretained id o1;
    101         int i3;
    102         __unsafe_unretained id o3;
    103   }ui;
    104 
    105   struct S5 s2;
    106   union U u2;
    107   __block id block_id;
    108 
    109 /**
    110 block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, 
    111                        BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0
    112 */
    113 // CHECK: block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0
    114   void (^c)() = ^{
    115     x(s2.ui.o1);
    116     x(u2.o1);
    117     block_id = 0;
    118   };
    119   c();
    120 }
    121 
    122 // Test for array of stuff.
    123 void arr1() {
    124   struct S {
    125     __unsafe_unretained id unsafe_unretained_var[4];
    126  } imported_s;
    127 
    128 // CHECK: block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0
    129     void (^c)() = ^{
    130         x(imported_s.unsafe_unretained_var[2]);
    131     };    
    132 
    133    c();
    134 }
    135 
    136 // Test2 for array of stuff.
    137 void arr2() {
    138   struct S {
    139    int a;
    140     __unsafe_unretained id unsafe_unretained_var[4];
    141  } imported_s;
    142 
    143 // CHECK: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0
    144     void (^c)() = ^{
    145         x(imported_s.unsafe_unretained_var[2]);
    146     };    
    147 
    148    c();
    149 }
    150 
    151 // Test3 for array of stuff.
    152 void arr3() {
    153   struct S {
    154    int a;
    155     __unsafe_unretained id unsafe_unretained_var[0];
    156  } imported_s;
    157 
    158 // CHECK: block variable layout: BL_OPERATOR:0
    159     void (^c)() = ^{
    160       int i = imported_s.a;
    161     };    
    162 
    163    c();
    164 }
    165 
    166 
    167 // Test4 for array of stuff.
    168 @class B;
    169 void arr4() {
    170   struct S {
    171     struct s0 {
    172       __unsafe_unretained id s_f0;
    173       __unsafe_unretained id s_f1;
    174     } f0;
    175 
    176     __unsafe_unretained id f1;
    177 
    178     struct s1 {
    179       int *f0;
    180       __unsafe_unretained B *f1;
    181     } f4[2][2];
    182   } captured_s;
    183 
    184 // CHECK: block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0
    185   void (^c)() = ^{
    186       id i = captured_s.f0.s_f1;
    187   };
    188 
    189    c();
    190 }
    191 
    192 // Test1 bitfield in cpatured aggregate.
    193 void bf1() {
    194   struct S {
    195     int flag : 25;
    196     int flag1: 7;
    197     int flag2 :1;
    198     int flag3: 7;
    199     int flag4: 24;
    200   } s;
    201 
    202 // CHECK:  block variable layout: BL_OPERATOR:0
    203   int (^c)() = ^{
    204       return s.flag;
    205   };
    206   c();
    207 }
    208 
    209 // Test2 bitfield in cpatured aggregate.
    210 void bf2() {
    211   struct S {
    212     int flag : 1;
    213   } s;
    214 
    215 // CHECK: block variable layout: BL_OPERATOR:0
    216   int (^c)() = ^{
    217       return s.flag;
    218   };
    219   c();
    220 }
    221 
    222 // Test3 bitfield in cpatured aggregate.
    223 void bf3() {
    224 
    225      struct {
    226         unsigned short _reserved : 16;
    227 
    228         unsigned char _draggedNodesAreDeletable: 1;
    229         unsigned char _draggedOutsideOutlineView : 1;
    230         unsigned char _adapterRespondsTo_addRootPaths : 1;
    231         unsigned char _adapterRespondsTo_moveDataNodes : 1;
    232         unsigned char _adapterRespondsTo_removeRootDataNode : 1;
    233         unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
    234         unsigned char _adapterRespondsTo_selectDataNode : 1;
    235         unsigned char _adapterRespondsTo_textDidEndEditing : 1;
    236         unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
    237         unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
    238         unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
    239         unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
    240         unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
    241         unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
    242 
    243         unsigned int _filler : 32;
    244     } _flags;
    245 
    246 // CHECK: block variable layout: BL_OPERATOR:0
    247   unsigned char (^c)() = ^{
    248       return _flags._draggedNodesAreDeletable;
    249   };
    250 
    251    c();
    252 }
    253 
    254 // Test4 unnamed bitfield
    255 void bf4() {
    256 
    257      struct {
    258         unsigned short _reserved : 16;
    259 
    260         unsigned char _draggedNodesAreDeletable: 1;
    261         unsigned char _draggedOutsideOutlineView : 1;
    262         unsigned char _adapterRespondsTo_addRootPaths : 1;
    263         unsigned char _adapterRespondsTo_moveDataNodes : 1;
    264         unsigned char _adapterRespondsTo_removeRootDataNode : 1;
    265         unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
    266         unsigned char _adapterRespondsTo_selectDataNode : 1;
    267         unsigned char _adapterRespondsTo_textDidEndEditing : 1;
    268 
    269         unsigned long long : 64;
    270 
    271         unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
    272         unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
    273         unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
    274         unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
    275         unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
    276         unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
    277 
    278         unsigned int _filler : 32;
    279     } _flags;
    280 
    281 // CHECK:  block variable layout: BL_OPERATOR:0
    282   unsigned char (^c)() = ^{
    283       return _flags._draggedNodesAreDeletable;
    284   };
    285 
    286    c();
    287 }
    288 
    289 
    290 
    291 // Test5 unnamed bitfield.
    292 void bf5() {
    293      struct {
    294         unsigned char flag : 1;
    295         unsigned int  : 32;
    296         unsigned char flag1 : 1;
    297     } _flags;
    298 
    299 // CHECK:  block variable layout: BL_OPERATOR:0
    300   unsigned char (^c)() = ^{
    301       return _flags.flag;
    302   };
    303 
    304    c();
    305 }
    306 
    307 
    308 // Test6 0 length bitfield.
    309 void bf6() {
    310      struct {
    311         unsigned char flag : 1;
    312         unsigned int  : 0;
    313         unsigned char flag1 : 1;
    314     } _flags;
    315 
    316 // CHECK: block variable layout: BL_OPERATOR:0
    317   unsigned char (^c)() = ^{
    318       return _flags.flag;
    319   };
    320 
    321    c();
    322 }
    323 
    324 // Test7 large number of captured variables.
    325 void Test7() {
    326     __weak id wid;
    327     __weak id wid1, wid2, wid3, wid4;
    328     __weak id wid5, wid6, wid7, wid8;
    329     __weak id wid9, wid10, wid11, wid12;
    330     __weak id wid13, wid14, wid15, wid16;
    331     const id bar = (id) opaque_id();
    332 // CHECK: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0
    333     void (^b)() = ^{
    334       x(bar);
    335       x(wid1);
    336       x(wid2);
    337       x(wid3);
    338       x(wid4);
    339       x(wid5);
    340       x(wid6);
    341       x(wid7);
    342       x(wid8);
    343       x(wid9);
    344       x(wid10);
    345       x(wid11);
    346       x(wid12);
    347       x(wid13);
    348       x(wid14);
    349       x(wid15);
    350       x(wid16);
    351     };    
    352 }
    353 
    354 
    355 // Test 8 very large number of captured variables.
    356 void Test8() {
    357 __weak id wid;
    358     __weak id wid1, wid2, wid3, wid4;
    359     __weak id wid5, wid6, wid7, wid8;
    360     __weak id wid9, wid10, wid11, wid12;
    361     __weak id wid13, wid14, wid15, wid16;
    362     __weak id w1, w2, w3, w4;
    363     __weak id w5, w6, w7, w8;
    364     __weak id w9, w10, w11, w12;
    365     __weak id w13, w14, w15, w16;
    366     const id bar = (id) opaque_id();
    367 // CHECK: block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0
    368     void (^b)() = ^{
    369       x(bar);
    370       x(wid1);
    371       x(wid2);
    372       x(wid3);
    373       x(wid4);
    374       x(wid5);
    375       x(wid6);
    376       x(wid7);
    377       x(wid8);
    378       x(wid9);
    379       x(wid10);
    380       x(wid11);
    381       x(wid12);
    382       x(wid13);
    383       x(wid14);
    384       x(wid15);
    385       x(wid16);
    386       x(w1);
    387       x(w2);
    388       x(w3);
    389       x(w4);
    390       x(w5);
    391       x(w6);
    392       x(w7);
    393       x(w8);
    394       x(w9);
    395       x(w10);
    396       x(w11);
    397       x(w12);
    398       x(w13);
    399       x(w14);
    400       x(w15);
    401       x(w16);
    402       x(wid);
    403     };  
    404 }
    405