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