Home | History | Annotate | Download | only in CodeGenObjC
      1 // RUN: %clang_cc1 -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 -O0 -emit-llvm %s -o %t-64.s
      2 // RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s
      3 
      4 struct S {
      5     int i1;
      6     id o1;
      7     struct V {
      8      int i2;
      9      id o2;
     10     } v1;
     11     int i3;
     12     id o3;
     13 };
     14 
     15 __weak id wid;
     16 void x(id y) {}
     17 void y(int a) {}
     18 
     19 extern id opaque_id();
     20 
     21 void f() {
     22     __block int byref_int = 0;
     23     char ch = 'a';
     24     char ch1 = 'b';
     25     char ch2 = 'c';
     26     short sh = 2;
     27     const id bar = (id) opaque_id();
     28     id baz = 0;
     29     __strong void *strong_void_sta;
     30     __block id byref_bab = (id)0;
     31     __block void *bl_var1;
     32     int i; double dob;
     33 
     34 // The patterns here are a sequence of bytes, each saying first how
     35 // many sizeof(void*) chunks to skip (high nibble) and then how many
     36 // to scan (low nibble).  A zero byte says that we've reached the end
     37 // of the pattern.
     38 //
     39 // All of these patterns start with 01 3x because the block header on
     40 // LP64 consists of an isa pointer (which we're supposed to scan for
     41 // some reason) followed by three words (2 ints, a function pointer,
     42 // and a descriptor pointer).
     43 
     44 // FIXME: do these really have to be named L_OBJC_CLASS_NAME_xxx?
     45 // FIXME: sequences should never end in x0 00 instead of just 00
     46 
     47 // Test 1
     48 // byref int, short, char, char, char, id, id, strong void*, byref id
     49 // 01 35 10 00
     50 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00"
     51     void (^b)() = ^{
     52         byref_int = sh + ch+ch1+ch2 ;
     53         x(bar);
     54         x(baz);
     55         x((id)strong_void_sta);
     56         x(byref_bab);
     57     };    
     58     b();
     59 
     60 // Test 2
     61 // byref int, short, char, char, char, id, id, strong void*, byref void*, byref id
     62 // 01 36 10 00
     63 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00"
     64     void (^c)() = ^{
     65         byref_int = sh + ch+ch1+ch2 ;
     66         x(bar);
     67         x(baz);
     68         x((id)strong_void_sta);
     69         x(wid);
     70         bl_var1 = 0;
     71         x(byref_bab);
     72     };    
     73     c();
     74 
     75 // Test 3
     76 // byref int, short, char, char, char, id, id, byref void*, int, double, byref id
     77 // 01 34 11 30 00
     78 // FIXME: we'd get a better format here if we sorted by scannability, not just alignment
     79 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00"
     80     void (^d)() = ^{
     81         byref_int = sh + ch+ch1+ch2 ;
     82         x(bar);
     83         x(baz);
     84         x(wid);
     85         bl_var1 = 0; 
     86         y(i + dob);
     87         x(byref_bab);
     88     };    
     89     d();
     90 
     91 // Test 4
     92 // struct S (int, id, int, id, int, id)
     93 // 01 41 11 11
     94 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00"
     95     struct S s2;
     96     void (^e)() = ^{
     97         x(s2.o1);
     98     };    
     99     e();
    100 }
    101 
    102 // Test 5 (unions/structs and their nesting):
    103 void Test5() {
    104   struct S5 {
    105     int i1;
    106     id o1;
    107     struct V {
    108      int i2;
    109      id o2;
    110     } v1;
    111     int i3;
    112     union UI {
    113         void * i1;
    114         id o1;
    115         int i3;
    116         id o3;
    117     }ui;
    118   };
    119 
    120   union U {
    121         void * i1;
    122         id o1;
    123         int i3;
    124         id o3;
    125   }ui;
    126 
    127   struct S5 s2;
    128   union U u2;
    129 
    130 // struct s2 (int, id, int, id, int, id?), union u2 (id?)
    131 // 01 41 11 12 70 00
    132 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [6 x i8] c"\01A\11\12p\00"
    133   void (^c)() = ^{
    134     x(s2.ui.o1);
    135     x(u2.o1);
    136   };
    137   c();
    138 }
    139 
    140 // rdar: //8417746
    141 void CFRelease(id);
    142 void notifyBlock(id dependentBlock) {
    143  id singleObservationToken;
    144  id token;
    145  void (^b)();
    146 
    147 // id, id, void(^)()
    148 // 01 33 00
    149 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00"
    150  void (^wrapperBlock)() = ^() {
    151      CFRelease(singleObservationToken);
    152      CFRelease(singleObservationToken);
    153      CFRelease(token);
    154      CFRelease(singleObservationToken);
    155      b();
    156     };
    157  wrapperBlock();
    158 }
    159 
    160 void test_empty_block() {
    161 // 01 00
    162 // CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00"
    163   void (^wrapperBlock)() = ^() {
    164   };
    165  wrapperBlock();
    166 }
    167