xref: /aosp_15_r20/external/clang/docs/Block-ABI-Apple.rst (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li==================================
2*67e74705SXin LiBlock Implementation Specification
3*67e74705SXin Li==================================
4*67e74705SXin Li
5*67e74705SXin Li.. contents::
6*67e74705SXin Li   :local:
7*67e74705SXin Li
8*67e74705SXin LiHistory
9*67e74705SXin Li=======
10*67e74705SXin Li
11*67e74705SXin Li* 2008/7/14 - created.
12*67e74705SXin Li* 2008/8/21 - revised, C++.
13*67e74705SXin Li* 2008/9/24 - add ``NULL`` ``isa`` field to ``__block`` storage.
14*67e74705SXin Li* 2008/10/1 - revise block layout to use a ``static`` descriptor structure.
15*67e74705SXin Li* 2008/10/6 - revise block layout to use an unsigned long int flags.
16*67e74705SXin Li* 2008/10/28 - specify use of ``_Block_object_assign`` and
17*67e74705SXin Li  ``_Block_object_dispose`` for all "Object" types in helper functions.
18*67e74705SXin Li* 2008/10/30 - revise new layout to have invoke function in same place.
19*67e74705SXin Li* 2008/10/30 - add ``__weak`` support.
20*67e74705SXin Li* 2010/3/16 - rev for stret return, signature field.
21*67e74705SXin Li* 2010/4/6 - improved wording.
22*67e74705SXin Li* 2013/1/6 - improved wording and converted to rst.
23*67e74705SXin Li
24*67e74705SXin LiThis document describes the Apple ABI implementation specification of Blocks.
25*67e74705SXin Li
26*67e74705SXin LiThe first shipping version of this ABI is found in Mac OS X 10.6, and shall be
27*67e74705SXin Lireferred to as 10.6.ABI. As of 2010/3/16, the following describes the ABI
28*67e74705SXin Licontract with the runtime and the compiler, and, as necessary, will be referred
29*67e74705SXin Lito as ABI.2010.3.16.
30*67e74705SXin Li
31*67e74705SXin LiSince the Apple ABI references symbols from other elements of the system, any
32*67e74705SXin Liattempt to use this ABI on systems prior to SnowLeopard is undefined.
33*67e74705SXin Li
34*67e74705SXin LiHigh Level
35*67e74705SXin Li==========
36*67e74705SXin Li
37*67e74705SXin LiThe ABI of ``Blocks`` consist of their layout and the runtime functions required
38*67e74705SXin Liby the compiler.  A ``Block`` consists of a structure of the following form:
39*67e74705SXin Li
40*67e74705SXin Li.. code-block:: c
41*67e74705SXin Li
42*67e74705SXin Li    struct Block_literal_1 {
43*67e74705SXin Li        void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
44*67e74705SXin Li        int flags;
45*67e74705SXin Li        int reserved;
46*67e74705SXin Li        void (*invoke)(void *, ...);
47*67e74705SXin Li        struct Block_descriptor_1 {
48*67e74705SXin Li        unsigned long int reserved;         // NULL
49*67e74705SXin Li            unsigned long int size;         // sizeof(struct Block_literal_1)
50*67e74705SXin Li            // optional helper functions
51*67e74705SXin Li            void (*copy_helper)(void *dst, void *src);     // IFF (1<<25)
52*67e74705SXin Li            void (*dispose_helper)(void *src);             // IFF (1<<25)
53*67e74705SXin Li            // required ABI.2010.3.16
54*67e74705SXin Li            const char *signature;                         // IFF (1<<30)
55*67e74705SXin Li        } *descriptor;
56*67e74705SXin Li        // imported variables
57*67e74705SXin Li    };
58*67e74705SXin Li
59*67e74705SXin LiThe following flags bits are in use thusly for a possible ABI.2010.3.16:
60*67e74705SXin Li
61*67e74705SXin Li.. code-block:: c
62*67e74705SXin Li
63*67e74705SXin Li    enum {
64*67e74705SXin Li        BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
65*67e74705SXin Li        BLOCK_HAS_CTOR =          (1 << 26), // helpers have C++ code
66*67e74705SXin Li        BLOCK_IS_GLOBAL =         (1 << 28),
67*67e74705SXin Li        BLOCK_HAS_STRET =         (1 << 29), // IFF BLOCK_HAS_SIGNATURE
68*67e74705SXin Li        BLOCK_HAS_SIGNATURE =     (1 << 30),
69*67e74705SXin Li    };
70*67e74705SXin Li
71*67e74705SXin LiIn 10.6.ABI the (1<<29) was usually set and was always ignored by the runtime -
72*67e74705SXin Liit had been a transitional marker that did not get deleted after the
73*67e74705SXin Litransition. This bit is now paired with (1<<30), and represented as the pair
74*67e74705SXin Li(3<<30), for the following combinations of valid bit settings, and their
75*67e74705SXin Limeanings:
76*67e74705SXin Li
77*67e74705SXin Li.. code-block:: c
78*67e74705SXin Li
79*67e74705SXin Li    switch (flags & (3<<29)) {
80*67e74705SXin Li      case (0<<29):      10.6.ABI, no signature field available
81*67e74705SXin Li      case (1<<29):      10.6.ABI, no signature field available
82*67e74705SXin Li      case (2<<29): ABI.2010.3.16, regular calling convention, presence of signature field
83*67e74705SXin Li      case (3<<29): ABI.2010.3.16, stret calling convention, presence of signature field,
84*67e74705SXin Li    }
85*67e74705SXin Li
86*67e74705SXin LiThe signature field is not always populated.
87*67e74705SXin Li
88*67e74705SXin LiThe following discussions are presented as 10.6.ABI otherwise.
89*67e74705SXin Li
90*67e74705SXin Li``Block`` literals may occur within functions where the structure is created in
91*67e74705SXin Listack local memory.  They may also appear as initialization expressions for
92*67e74705SXin Li``Block`` variables of global or ``static`` local variables.
93*67e74705SXin Li
94*67e74705SXin LiWhen a ``Block`` literal expression is evaluated the stack based structure is
95*67e74705SXin Liinitialized as follows:
96*67e74705SXin Li
97*67e74705SXin Li1. A ``static`` descriptor structure is declared and initialized as follows:
98*67e74705SXin Li
99*67e74705SXin Li  a. The ``invoke`` function pointer is set to a function that takes the
100*67e74705SXin Li  ``Block`` structure as its first argument and the rest of the arguments (if
101*67e74705SXin Li  any) to the ``Block`` and executes the ``Block`` compound statement.
102*67e74705SXin Li
103*67e74705SXin Li  b. The ``size`` field is set to the size of the following ``Block`` literal
104*67e74705SXin Li  structure.
105*67e74705SXin Li
106*67e74705SXin Li  c. The ``copy_helper`` and ``dispose_helper`` function pointers are set to
107*67e74705SXin Li  respective helper functions if they are required by the ``Block`` literal.
108*67e74705SXin Li
109*67e74705SXin Li2. A stack (or global) ``Block`` literal data structure is created and
110*67e74705SXin Li   initialized as follows:
111*67e74705SXin Li
112*67e74705SXin Li   a. The ``isa`` field is set to the address of the external
113*67e74705SXin Li   ``_NSConcreteStackBlock``, which is a block of uninitialized memory supplied
114*67e74705SXin Li   in ``libSystem``, or ``_NSConcreteGlobalBlock`` if this is a static or file
115*67e74705SXin Li   level ``Block`` literal.
116*67e74705SXin Li
117*67e74705SXin Li   b. The ``flags`` field is set to zero unless there are variables imported
118*67e74705SXin Li   into the ``Block`` that need helper functions for program level
119*67e74705SXin Li   ``Block_copy()`` and ``Block_release()`` operations, in which case the
120*67e74705SXin Li   (1<<25) flags bit is set.
121*67e74705SXin Li
122*67e74705SXin LiAs an example, the ``Block`` literal expression:
123*67e74705SXin Li
124*67e74705SXin Li.. code-block:: c
125*67e74705SXin Li
126*67e74705SXin Li    ^ { printf("hello world\n"); }
127*67e74705SXin Li
128*67e74705SXin Liwould cause the following to be created on a 32-bit system:
129*67e74705SXin Li
130*67e74705SXin Li.. code-block:: c
131*67e74705SXin Li
132*67e74705SXin Li    struct __block_literal_1 {
133*67e74705SXin Li        void *isa;
134*67e74705SXin Li        int flags;
135*67e74705SXin Li        int reserved;
136*67e74705SXin Li        void (*invoke)(struct __block_literal_1 *);
137*67e74705SXin Li        struct __block_descriptor_1 *descriptor;
138*67e74705SXin Li    };
139*67e74705SXin Li
140*67e74705SXin Li    void __block_invoke_1(struct __block_literal_1 *_block) {
141*67e74705SXin Li        printf("hello world\n");
142*67e74705SXin Li    }
143*67e74705SXin Li
144*67e74705SXin Li    static struct __block_descriptor_1 {
145*67e74705SXin Li        unsigned long int reserved;
146*67e74705SXin Li        unsigned long int Block_size;
147*67e74705SXin Li    } __block_descriptor_1 = { 0, sizeof(struct __block_literal_1), __block_invoke_1 };
148*67e74705SXin Li
149*67e74705SXin Liand where the ``Block`` literal itself appears:
150*67e74705SXin Li
151*67e74705SXin Li.. code-block:: c
152*67e74705SXin Li
153*67e74705SXin Li    struct __block_literal_1 _block_literal = {
154*67e74705SXin Li         &_NSConcreteStackBlock,
155*67e74705SXin Li         (1<<29), <uninitialized>,
156*67e74705SXin Li         __block_invoke_1,
157*67e74705SXin Li         &__block_descriptor_1
158*67e74705SXin Li    };
159*67e74705SXin Li
160*67e74705SXin LiA ``Block`` imports other ``Block`` references, ``const`` copies of other
161*67e74705SXin Livariables, and variables marked ``__block``.  In Objective-C, variables may
162*67e74705SXin Liadditionally be objects.
163*67e74705SXin Li
164*67e74705SXin LiWhen a ``Block`` literal expression is used as the initial value of a global
165*67e74705SXin Lior ``static`` local variable, it is initialized as follows:
166*67e74705SXin Li
167*67e74705SXin Li.. code-block:: c
168*67e74705SXin Li
169*67e74705SXin Li    struct __block_literal_1 __block_literal_1 = {
170*67e74705SXin Li          &_NSConcreteGlobalBlock,
171*67e74705SXin Li          (1<<28)|(1<<29), <uninitialized>,
172*67e74705SXin Li          __block_invoke_1,
173*67e74705SXin Li          &__block_descriptor_1
174*67e74705SXin Li    };
175*67e74705SXin Li
176*67e74705SXin Lithat is, a different address is provided as the first value and a particular
177*67e74705SXin Li(1<<28) bit is set in the ``flags`` field, and otherwise it is the same as for
178*67e74705SXin Listack based ``Block`` literals.  This is an optimization that can be used for
179*67e74705SXin Liany ``Block`` literal that imports no ``const`` or ``__block`` storage
180*67e74705SXin Livariables.
181*67e74705SXin Li
182*67e74705SXin LiImported Variables
183*67e74705SXin Li==================
184*67e74705SXin Li
185*67e74705SXin LiVariables of ``auto`` storage class are imported as ``const`` copies.  Variables
186*67e74705SXin Liof ``__block`` storage class are imported as a pointer to an enclosing data
187*67e74705SXin Listructure.  Global variables are simply referenced and not considered as
188*67e74705SXin Liimported.
189*67e74705SXin Li
190*67e74705SXin LiImported ``const`` copy variables
191*67e74705SXin Li---------------------------------
192*67e74705SXin Li
193*67e74705SXin LiAutomatic storage variables not marked with ``__block`` are imported as
194*67e74705SXin Li``const`` copies.
195*67e74705SXin Li
196*67e74705SXin LiThe simplest example is that of importing a variable of type ``int``:
197*67e74705SXin Li
198*67e74705SXin Li.. code-block:: c
199*67e74705SXin Li
200*67e74705SXin Li    int x = 10;
201*67e74705SXin Li    void (^vv)(void) = ^{ printf("x is %d\n", x); }
202*67e74705SXin Li    x = 11;
203*67e74705SXin Li    vv();
204*67e74705SXin Li
205*67e74705SXin Liwhich would be compiled to:
206*67e74705SXin Li
207*67e74705SXin Li.. code-block:: c
208*67e74705SXin Li
209*67e74705SXin Li    struct __block_literal_2 {
210*67e74705SXin Li        void *isa;
211*67e74705SXin Li        int flags;
212*67e74705SXin Li        int reserved;
213*67e74705SXin Li        void (*invoke)(struct __block_literal_2 *);
214*67e74705SXin Li        struct __block_descriptor_2 *descriptor;
215*67e74705SXin Li        const int x;
216*67e74705SXin Li    };
217*67e74705SXin Li
218*67e74705SXin Li    void __block_invoke_2(struct __block_literal_2 *_block) {
219*67e74705SXin Li        printf("x is %d\n", _block->x);
220*67e74705SXin Li    }
221*67e74705SXin Li
222*67e74705SXin Li    static struct __block_descriptor_2 {
223*67e74705SXin Li        unsigned long int reserved;
224*67e74705SXin Li        unsigned long int Block_size;
225*67e74705SXin Li    } __block_descriptor_2 = { 0, sizeof(struct __block_literal_2) };
226*67e74705SXin Li
227*67e74705SXin Liand:
228*67e74705SXin Li
229*67e74705SXin Li.. code-block:: c
230*67e74705SXin Li
231*67e74705SXin Li    struct __block_literal_2 __block_literal_2 = {
232*67e74705SXin Li          &_NSConcreteStackBlock,
233*67e74705SXin Li          (1<<29), <uninitialized>,
234*67e74705SXin Li          __block_invoke_2,
235*67e74705SXin Li          &__block_descriptor_2,
236*67e74705SXin Li          x
237*67e74705SXin Li     };
238*67e74705SXin Li
239*67e74705SXin LiIn summary, scalars, structures, unions, and function pointers are generally
240*67e74705SXin Liimported as ``const`` copies with no need for helper functions.
241*67e74705SXin Li
242*67e74705SXin LiImported ``const`` copy of ``Block`` reference
243*67e74705SXin Li----------------------------------------------
244*67e74705SXin Li
245*67e74705SXin LiThe first case where copy and dispose helper functions are required is for the
246*67e74705SXin Licase of when a ``Block`` itself is imported.  In this case both a
247*67e74705SXin Li``copy_helper`` function and a ``dispose_helper`` function are needed.  The
248*67e74705SXin Li``copy_helper`` function is passed both the existing stack based pointer and the
249*67e74705SXin Lipointer to the new heap version and should call back into the runtime to
250*67e74705SXin Liactually do the copy operation on the imported fields within the ``Block``. The
251*67e74705SXin Liruntime functions are all described in :ref:`RuntimeHelperFunctions`.
252*67e74705SXin Li
253*67e74705SXin LiA quick example:
254*67e74705SXin Li
255*67e74705SXin Li.. code-block:: c
256*67e74705SXin Li
257*67e74705SXin Li    void (^existingBlock)(void) = ...;
258*67e74705SXin Li    void (^vv)(void) = ^{ existingBlock(); }
259*67e74705SXin Li    vv();
260*67e74705SXin Li
261*67e74705SXin Li    struct __block_literal_3 {
262*67e74705SXin Li       ...; // existing block
263*67e74705SXin Li    };
264*67e74705SXin Li
265*67e74705SXin Li    struct __block_literal_4 {
266*67e74705SXin Li        void *isa;
267*67e74705SXin Li        int flags;
268*67e74705SXin Li        int reserved;
269*67e74705SXin Li        void (*invoke)(struct __block_literal_4 *);
270*67e74705SXin Li        struct __block_literal_3 *const existingBlock;
271*67e74705SXin Li    };
272*67e74705SXin Li
273*67e74705SXin Li    void __block_invoke_4(struct __block_literal_2 *_block) {
274*67e74705SXin Li       __block->existingBlock->invoke(__block->existingBlock);
275*67e74705SXin Li    }
276*67e74705SXin Li
277*67e74705SXin Li    void __block_copy_4(struct __block_literal_4 *dst, struct __block_literal_4 *src) {
278*67e74705SXin Li         //_Block_copy_assign(&dst->existingBlock, src->existingBlock, 0);
279*67e74705SXin Li         _Block_object_assign(&dst->existingBlock, src->existingBlock, BLOCK_FIELD_IS_BLOCK);
280*67e74705SXin Li    }
281*67e74705SXin Li
282*67e74705SXin Li    void __block_dispose_4(struct __block_literal_4 *src) {
283*67e74705SXin Li         // was _Block_destroy
284*67e74705SXin Li         _Block_object_dispose(src->existingBlock, BLOCK_FIELD_IS_BLOCK);
285*67e74705SXin Li    }
286*67e74705SXin Li
287*67e74705SXin Li    static struct __block_descriptor_4 {
288*67e74705SXin Li        unsigned long int reserved;
289*67e74705SXin Li        unsigned long int Block_size;
290*67e74705SXin Li        void (*copy_helper)(struct __block_literal_4 *dst, struct __block_literal_4 *src);
291*67e74705SXin Li        void (*dispose_helper)(struct __block_literal_4 *);
292*67e74705SXin Li    } __block_descriptor_4 = {
293*67e74705SXin Li        0,
294*67e74705SXin Li        sizeof(struct __block_literal_4),
295*67e74705SXin Li        __block_copy_4,
296*67e74705SXin Li        __block_dispose_4,
297*67e74705SXin Li    };
298*67e74705SXin Li
299*67e74705SXin Liand where said ``Block`` is used:
300*67e74705SXin Li
301*67e74705SXin Li.. code-block:: c
302*67e74705SXin Li
303*67e74705SXin Li    struct __block_literal_4 _block_literal = {
304*67e74705SXin Li          &_NSConcreteStackBlock,
305*67e74705SXin Li          (1<<25)|(1<<29), <uninitialized>
306*67e74705SXin Li          __block_invoke_4,
307*67e74705SXin Li          & __block_descriptor_4
308*67e74705SXin Li          existingBlock,
309*67e74705SXin Li    };
310*67e74705SXin Li
311*67e74705SXin LiImporting ``__attribute__((NSObject))`` variables
312*67e74705SXin Li^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
313*67e74705SXin Li
314*67e74705SXin LiGCC introduces ``__attribute__((NSObject))`` on structure pointers to mean "this
315*67e74705SXin Liis an object".  This is useful because many low level data structures are
316*67e74705SXin Lideclared as opaque structure pointers, e.g. ``CFStringRef``, ``CFArrayRef``,
317*67e74705SXin Lietc.  When used from C, however, these are still really objects and are the
318*67e74705SXin Lisecond case where that requires copy and dispose helper functions to be
319*67e74705SXin Ligenerated.  The copy helper functions generated by the compiler should use the
320*67e74705SXin Li``_Block_object_assign`` runtime helper function and in the dispose helper the
321*67e74705SXin Li``_Block_object_dispose`` runtime helper function should be called.
322*67e74705SXin Li
323*67e74705SXin LiFor example, ``Block`` foo in the following:
324*67e74705SXin Li
325*67e74705SXin Li.. code-block:: c
326*67e74705SXin Li
327*67e74705SXin Li    struct Opaque *__attribute__((NSObject)) objectPointer = ...;
328*67e74705SXin Li    ...
329*67e74705SXin Li    void (^foo)(void) = ^{  CFPrint(objectPointer); };
330*67e74705SXin Li
331*67e74705SXin Liwould have the following helper functions generated:
332*67e74705SXin Li
333*67e74705SXin Li.. code-block:: c
334*67e74705SXin Li
335*67e74705SXin Li    void __block_copy_foo(struct __block_literal_5 *dst, struct __block_literal_5 *src) {
336*67e74705SXin Li         _Block_object_assign(&dst->objectPointer, src-> objectPointer, BLOCK_FIELD_IS_OBJECT);
337*67e74705SXin Li    }
338*67e74705SXin Li
339*67e74705SXin Li    void __block_dispose_foo(struct __block_literal_5 *src) {
340*67e74705SXin Li         _Block_object_dispose(src->objectPointer, BLOCK_FIELD_IS_OBJECT);
341*67e74705SXin Li    }
342*67e74705SXin Li
343*67e74705SXin LiImported ``__block`` marked variables
344*67e74705SXin Li-------------------------------------
345*67e74705SXin Li
346*67e74705SXin LiLayout of ``__block`` marked variables
347*67e74705SXin Li^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
348*67e74705SXin Li
349*67e74705SXin LiThe compiler must embed variables that are marked ``__block`` in a specialized
350*67e74705SXin Listructure of the form:
351*67e74705SXin Li
352*67e74705SXin Li.. code-block:: c
353*67e74705SXin Li
354*67e74705SXin Li    struct _block_byref_foo {
355*67e74705SXin Li        void *isa;
356*67e74705SXin Li        struct Block_byref *forwarding;
357*67e74705SXin Li        int flags;   //refcount;
358*67e74705SXin Li        int size;
359*67e74705SXin Li        typeof(marked_variable) marked_variable;
360*67e74705SXin Li    };
361*67e74705SXin Li
362*67e74705SXin LiVariables of certain types require helper functions for when ``Block_copy()``
363*67e74705SXin Liand ``Block_release()`` are performed upon a referencing ``Block``.  At the "C"
364*67e74705SXin Lilevel only variables that are of type ``Block`` or ones that have
365*67e74705SXin Li``__attribute__((NSObject))`` marked require helper functions.  In Objective-C
366*67e74705SXin Liobjects require helper functions and in C++ stack based objects require helper
367*67e74705SXin Lifunctions. Variables that require helper functions use the form:
368*67e74705SXin Li
369*67e74705SXin Li.. code-block:: c
370*67e74705SXin Li
371*67e74705SXin Li    struct _block_byref_foo {
372*67e74705SXin Li        void *isa;
373*67e74705SXin Li        struct _block_byref_foo *forwarding;
374*67e74705SXin Li        int flags;   //refcount;
375*67e74705SXin Li        int size;
376*67e74705SXin Li        // helper functions called via Block_copy() and Block_release()
377*67e74705SXin Li        void (*byref_keep)(void  *dst, void *src);
378*67e74705SXin Li        void (*byref_dispose)(void *);
379*67e74705SXin Li        typeof(marked_variable) marked_variable;
380*67e74705SXin Li    };
381*67e74705SXin Li
382*67e74705SXin LiThe structure is initialized such that:
383*67e74705SXin Li
384*67e74705SXin Li    a. The ``forwarding`` pointer is set to the beginning of its enclosing
385*67e74705SXin Li    structure.
386*67e74705SXin Li
387*67e74705SXin Li    b. The ``size`` field is initialized to the total size of the enclosing
388*67e74705SXin Li    structure.
389*67e74705SXin Li
390*67e74705SXin Li    c. The ``flags`` field is set to either 0 if no helper functions are needed
391*67e74705SXin Li    or (1<<25) if they are.
392*67e74705SXin Li
393*67e74705SXin Li    d. The helper functions are initialized (if present).
394*67e74705SXin Li
395*67e74705SXin Li    e. The variable itself is set to its initial value.
396*67e74705SXin Li
397*67e74705SXin Li    f. The ``isa`` field is set to ``NULL``.
398*67e74705SXin Li
399*67e74705SXin LiAccess to ``__block`` variables from within its lexical scope
400*67e74705SXin Li^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
401*67e74705SXin Li
402*67e74705SXin LiIn order to "move" the variable to the heap upon a ``copy_helper`` operation the
403*67e74705SXin Licompiler must rewrite access to such a variable to be indirect through the
404*67e74705SXin Listructures ``forwarding`` pointer.  For example:
405*67e74705SXin Li
406*67e74705SXin Li.. code-block:: c
407*67e74705SXin Li
408*67e74705SXin Li    int __block i = 10;
409*67e74705SXin Li    i = 11;
410*67e74705SXin Li
411*67e74705SXin Liwould be rewritten to be:
412*67e74705SXin Li
413*67e74705SXin Li.. code-block:: c
414*67e74705SXin Li
415*67e74705SXin Li    struct _block_byref_i {
416*67e74705SXin Li      void *isa;
417*67e74705SXin Li      struct _block_byref_i *forwarding;
418*67e74705SXin Li      int flags;   //refcount;
419*67e74705SXin Li      int size;
420*67e74705SXin Li      int captured_i;
421*67e74705SXin Li    } i = { NULL, &i, 0, sizeof(struct _block_byref_i), 10 };
422*67e74705SXin Li
423*67e74705SXin Li    i.forwarding->captured_i = 11;
424*67e74705SXin Li
425*67e74705SXin LiIn the case of a ``Block`` reference variable being marked ``__block`` the
426*67e74705SXin Lihelper code generated must use the ``_Block_object_assign`` and
427*67e74705SXin Li``_Block_object_dispose`` routines supplied by the runtime to make the
428*67e74705SXin Licopies. For example:
429*67e74705SXin Li
430*67e74705SXin Li.. code-block:: c
431*67e74705SXin Li
432*67e74705SXin Li    __block void (voidBlock)(void) = blockA;
433*67e74705SXin Li    voidBlock = blockB;
434*67e74705SXin Li
435*67e74705SXin Liwould translate into:
436*67e74705SXin Li
437*67e74705SXin Li.. code-block:: c
438*67e74705SXin Li
439*67e74705SXin Li    struct _block_byref_voidBlock {
440*67e74705SXin Li        void *isa;
441*67e74705SXin Li        struct _block_byref_voidBlock *forwarding;
442*67e74705SXin Li        int flags;   //refcount;
443*67e74705SXin Li        int size;
444*67e74705SXin Li        void (*byref_keep)(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src);
445*67e74705SXin Li        void (*byref_dispose)(struct _block_byref_voidBlock *);
446*67e74705SXin Li        void (^captured_voidBlock)(void);
447*67e74705SXin Li    };
448*67e74705SXin Li
449*67e74705SXin Li    void _block_byref_keep_helper(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src) {
450*67e74705SXin Li        //_Block_copy_assign(&dst->captured_voidBlock, src->captured_voidBlock, 0);
451*67e74705SXin Li        _Block_object_assign(&dst->captured_voidBlock, src->captured_voidBlock, BLOCK_FIELD_IS_BLOCK | BLOCK_BYREF_CALLER);
452*67e74705SXin Li    }
453*67e74705SXin Li
454*67e74705SXin Li    void _block_byref_dispose_helper(struct _block_byref_voidBlock *param) {
455*67e74705SXin Li        //_Block_destroy(param->captured_voidBlock, 0);
456*67e74705SXin Li        _Block_object_dispose(param->captured_voidBlock, BLOCK_FIELD_IS_BLOCK | BLOCK_BYREF_CALLER)}
457*67e74705SXin Li
458*67e74705SXin Liand:
459*67e74705SXin Li
460*67e74705SXin Li.. code-block:: c
461*67e74705SXin Li
462*67e74705SXin Li    struct _block_byref_voidBlock voidBlock = {( .forwarding=&voidBlock, .flags=(1<<25), .size=sizeof(struct _block_byref_voidBlock *),
463*67e74705SXin Li        .byref_keep=_block_byref_keep_helper, .byref_dispose=_block_byref_dispose_helper,
464*67e74705SXin Li        .captured_voidBlock=blockA )};
465*67e74705SXin Li
466*67e74705SXin Li    voidBlock.forwarding->captured_voidBlock = blockB;
467*67e74705SXin Li
468*67e74705SXin LiImporting ``__block`` variables into ``Blocks``
469*67e74705SXin Li^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
470*67e74705SXin Li
471*67e74705SXin LiA ``Block`` that uses a ``__block`` variable in its compound statement body must
472*67e74705SXin Liimport the variable and emit ``copy_helper`` and ``dispose_helper`` helper
473*67e74705SXin Lifunctions that, in turn, call back into the runtime to actually copy or release
474*67e74705SXin Lithe ``byref`` data block using the functions ``_Block_object_assign`` and
475*67e74705SXin Li``_Block_object_dispose``.
476*67e74705SXin Li
477*67e74705SXin LiFor example:
478*67e74705SXin Li
479*67e74705SXin Li.. code-block:: c
480*67e74705SXin Li
481*67e74705SXin Li    int __block i = 2;
482*67e74705SXin Li    functioncall(^{ i = 10; });
483*67e74705SXin Li
484*67e74705SXin Liwould translate to:
485*67e74705SXin Li
486*67e74705SXin Li.. code-block:: c
487*67e74705SXin Li
488*67e74705SXin Li    struct _block_byref_i {
489*67e74705SXin Li        void *isa;  // set to NULL
490*67e74705SXin Li        struct _block_byref_voidBlock *forwarding;
491*67e74705SXin Li        int flags;   //refcount;
492*67e74705SXin Li        int size;
493*67e74705SXin Li        void (*byref_keep)(struct _block_byref_i *dst, struct _block_byref_i *src);
494*67e74705SXin Li        void (*byref_dispose)(struct _block_byref_i *);
495*67e74705SXin Li        int captured_i;
496*67e74705SXin Li    };
497*67e74705SXin Li
498*67e74705SXin Li
499*67e74705SXin Li    struct __block_literal_5 {
500*67e74705SXin Li        void *isa;
501*67e74705SXin Li        int flags;
502*67e74705SXin Li        int reserved;
503*67e74705SXin Li        void (*invoke)(struct __block_literal_5 *);
504*67e74705SXin Li        struct __block_descriptor_5 *descriptor;
505*67e74705SXin Li        struct _block_byref_i *i_holder;
506*67e74705SXin Li    };
507*67e74705SXin Li
508*67e74705SXin Li    void __block_invoke_5(struct __block_literal_5 *_block) {
509*67e74705SXin Li       _block->forwarding->captured_i = 10;
510*67e74705SXin Li    }
511*67e74705SXin Li
512*67e74705SXin Li    void __block_copy_5(struct __block_literal_5 *dst, struct __block_literal_5 *src) {
513*67e74705SXin Li         //_Block_byref_assign_copy(&dst->captured_i, src->captured_i);
514*67e74705SXin Li         _Block_object_assign(&dst->captured_i, src->captured_i, BLOCK_FIELD_IS_BYREF | BLOCK_BYREF_CALLER);
515*67e74705SXin Li    }
516*67e74705SXin Li
517*67e74705SXin Li    void __block_dispose_5(struct __block_literal_5 *src) {
518*67e74705SXin Li         //_Block_byref_release(src->captured_i);
519*67e74705SXin Li         _Block_object_dispose(src->captured_i, BLOCK_FIELD_IS_BYREF | BLOCK_BYREF_CALLER);
520*67e74705SXin Li    }
521*67e74705SXin Li
522*67e74705SXin Li    static struct __block_descriptor_5 {
523*67e74705SXin Li        unsigned long int reserved;
524*67e74705SXin Li        unsigned long int Block_size;
525*67e74705SXin Li        void (*copy_helper)(struct __block_literal_5 *dst, struct __block_literal_5 *src);
526*67e74705SXin Li        void (*dispose_helper)(struct __block_literal_5 *);
527*67e74705SXin Li    } __block_descriptor_5 = { 0, sizeof(struct __block_literal_5) __block_copy_5, __block_dispose_5 };
528*67e74705SXin Li
529*67e74705SXin Liand:
530*67e74705SXin Li
531*67e74705SXin Li.. code-block:: c
532*67e74705SXin Li
533*67e74705SXin Li    struct _block_byref_i i = {( .forwarding=&i, .flags=0, .size=sizeof(struct _block_byref_i) )};
534*67e74705SXin Li    struct __block_literal_5 _block_literal = {
535*67e74705SXin Li          &_NSConcreteStackBlock,
536*67e74705SXin Li          (1<<25)|(1<<29), <uninitialized>,
537*67e74705SXin Li          __block_invoke_5,
538*67e74705SXin Li          &__block_descriptor_5,
539*67e74705SXin Li          2,
540*67e74705SXin Li    };
541*67e74705SXin Li
542*67e74705SXin LiImporting ``__attribute__((NSObject))`` ``__block`` variables
543*67e74705SXin Li^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
544*67e74705SXin Li
545*67e74705SXin LiA ``__block`` variable that is also marked ``__attribute__((NSObject))`` should
546*67e74705SXin Lihave ``byref_keep`` and ``byref_dispose`` helper functions that use
547*67e74705SXin Li``_Block_object_assign`` and ``_Block_object_dispose``.
548*67e74705SXin Li
549*67e74705SXin Li``__block`` escapes
550*67e74705SXin Li^^^^^^^^^^^^^^^^^^^
551*67e74705SXin Li
552*67e74705SXin LiBecause ``Blocks`` referencing ``__block`` variables may have ``Block_copy()``
553*67e74705SXin Liperformed upon them the underlying storage for the variables may move to the
554*67e74705SXin Liheap.  In Objective-C Garbage Collection Only compilation environments the heap
555*67e74705SXin Liused is the garbage collected one and no further action is required.  Otherwise
556*67e74705SXin Lithe compiler must issue a call to potentially release any heap storage for
557*67e74705SXin Li``__block`` variables at all escapes or terminations of their scope.  The call
558*67e74705SXin Lishould be:
559*67e74705SXin Li
560*67e74705SXin Li.. code-block:: c
561*67e74705SXin Li
562*67e74705SXin Li    _Block_object_dispose(&_block_byref_foo, BLOCK_FIELD_IS_BYREF);
563*67e74705SXin Li
564*67e74705SXin LiNesting
565*67e74705SXin Li^^^^^^^
566*67e74705SXin Li
567*67e74705SXin Li``Blocks`` may contain ``Block`` literal expressions.  Any variables used within
568*67e74705SXin Liinner blocks are imported into all enclosing ``Block`` scopes even if the
569*67e74705SXin Livariables are not used. This includes ``const`` imports as well as ``__block``
570*67e74705SXin Livariables.
571*67e74705SXin Li
572*67e74705SXin LiObjective C Extensions to ``Blocks``
573*67e74705SXin Li====================================
574*67e74705SXin Li
575*67e74705SXin LiImporting Objects
576*67e74705SXin Li-----------------
577*67e74705SXin Li
578*67e74705SXin LiObjects should be treated as ``__attribute__((NSObject))`` variables; all
579*67e74705SXin Li``copy_helper``, ``dispose_helper``, ``byref_keep``, and ``byref_dispose``
580*67e74705SXin Lihelper functions should use ``_Block_object_assign`` and
581*67e74705SXin Li``_Block_object_dispose``.  There should be no code generated that uses
582*67e74705SXin Li``*-retain`` or ``*-release`` methods.
583*67e74705SXin Li
584*67e74705SXin Li``Blocks`` as Objects
585*67e74705SXin Li---------------------
586*67e74705SXin Li
587*67e74705SXin LiThe compiler will treat ``Blocks`` as objects when synthesizing property setters
588*67e74705SXin Liand getters, will characterize them as objects when generating garbage
589*67e74705SXin Licollection strong and weak layout information in the same manner as objects, and
590*67e74705SXin Liwill issue strong and weak write-barrier assignments in the same manner as
591*67e74705SXin Liobjects.
592*67e74705SXin Li
593*67e74705SXin Li``__weak __block`` Support
594*67e74705SXin Li--------------------------
595*67e74705SXin Li
596*67e74705SXin LiObjective-C (and Objective-C++) support the ``__weak`` attribute on ``__block``
597*67e74705SXin Livariables.  Under normal circumstances the compiler uses the Objective-C runtime
598*67e74705SXin Lihelper support functions ``objc_assign_weak`` and ``objc_read_weak``.  Both
599*67e74705SXin Lishould continue to be used for all reads and writes of ``__weak __block``
600*67e74705SXin Livariables:
601*67e74705SXin Li
602*67e74705SXin Li.. code-block:: c
603*67e74705SXin Li
604*67e74705SXin Li    objc_read_weak(&block->byref_i->forwarding->i)
605*67e74705SXin Li
606*67e74705SXin LiThe ``__weak`` variable is stored in a ``_block_byref_foo`` structure and the
607*67e74705SXin Li``Block`` has copy and dispose helpers for this structure that call:
608*67e74705SXin Li
609*67e74705SXin Li.. code-block:: c
610*67e74705SXin Li
611*67e74705SXin Li    _Block_object_assign(&dest->_block_byref_i, src-> _block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_BYREF);
612*67e74705SXin Li
613*67e74705SXin Liand:
614*67e74705SXin Li
615*67e74705SXin Li.. code-block:: c
616*67e74705SXin Li
617*67e74705SXin Li    _Block_object_dispose(src->_block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_BYREF);
618*67e74705SXin Li
619*67e74705SXin LiIn turn, the ``block_byref`` copy support helpers distinguish between whether
620*67e74705SXin Lithe ``__block`` variable is a ``Block`` or not and should either call:
621*67e74705SXin Li
622*67e74705SXin Li.. code-block:: c
623*67e74705SXin Li
624*67e74705SXin Li    _Block_object_assign(&dest->_block_byref_i, src->_block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_OBJECT | BLOCK_BYREF_CALLER);
625*67e74705SXin Li
626*67e74705SXin Lifor something declared as an object or:
627*67e74705SXin Li
628*67e74705SXin Li.. code-block:: c
629*67e74705SXin Li
630*67e74705SXin Li    _Block_object_assign(&dest->_block_byref_i, src->_block_byref_i, BLOCK_FIELD_IS_WEAK | BLOCK_FIELD_IS_BLOCK | BLOCK_BYREF_CALLER);
631*67e74705SXin Li
632*67e74705SXin Lifor something declared as a ``Block``.
633*67e74705SXin Li
634*67e74705SXin LiA full example follows:
635*67e74705SXin Li
636*67e74705SXin Li.. code-block:: c
637*67e74705SXin Li
638*67e74705SXin Li    __block __weak id obj = <initialization expression>;
639*67e74705SXin Li    functioncall(^{ [obj somemessage]; });
640*67e74705SXin Li
641*67e74705SXin Liwould translate to:
642*67e74705SXin Li
643*67e74705SXin Li.. code-block:: c
644*67e74705SXin Li
645*67e74705SXin Li    struct _block_byref_obj {
646*67e74705SXin Li        void *isa;  // uninitialized
647*67e74705SXin Li        struct _block_byref_obj *forwarding;
648*67e74705SXin Li        int flags;   //refcount;
649*67e74705SXin Li        int size;
650*67e74705SXin Li        void (*byref_keep)(struct _block_byref_i *dst, struct _block_byref_i *src);
651*67e74705SXin Li        void (*byref_dispose)(struct _block_byref_i *);
652*67e74705SXin Li        id captured_obj;
653*67e74705SXin Li    };
654*67e74705SXin Li
655*67e74705SXin Li    void _block_byref_obj_keep(struct _block_byref_voidBlock *dst, struct _block_byref_voidBlock *src) {
656*67e74705SXin Li        //_Block_copy_assign(&dst->captured_obj, src->captured_obj, 0);
657*67e74705SXin Li        _Block_object_assign(&dst->captured_obj, src->captured_obj, BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER);
658*67e74705SXin Li    }
659*67e74705SXin Li
660*67e74705SXin Li    void _block_byref_obj_dispose(struct _block_byref_voidBlock *param) {
661*67e74705SXin Li        //_Block_destroy(param->captured_obj, 0);
662*67e74705SXin Li        _Block_object_dispose(param->captured_obj, BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER);
663*67e74705SXin Li    };
664*67e74705SXin Li
665*67e74705SXin Lifor the block ``byref`` part and:
666*67e74705SXin Li
667*67e74705SXin Li.. code-block:: c
668*67e74705SXin Li
669*67e74705SXin Li    struct __block_literal_5 {
670*67e74705SXin Li        void *isa;
671*67e74705SXin Li        int flags;
672*67e74705SXin Li        int reserved;
673*67e74705SXin Li        void (*invoke)(struct __block_literal_5 *);
674*67e74705SXin Li        struct __block_descriptor_5 *descriptor;
675*67e74705SXin Li        struct _block_byref_obj *byref_obj;
676*67e74705SXin Li    };
677*67e74705SXin Li
678*67e74705SXin Li    void __block_invoke_5(struct __block_literal_5 *_block) {
679*67e74705SXin Li       [objc_read_weak(&_block->byref_obj->forwarding->captured_obj) somemessage];
680*67e74705SXin Li    }
681*67e74705SXin Li
682*67e74705SXin Li    void __block_copy_5(struct __block_literal_5 *dst, struct __block_literal_5 *src) {
683*67e74705SXin Li         //_Block_byref_assign_copy(&dst->byref_obj, src->byref_obj);
684*67e74705SXin Li         _Block_object_assign(&dst->byref_obj, src->byref_obj, BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK);
685*67e74705SXin Li    }
686*67e74705SXin Li
687*67e74705SXin Li    void __block_dispose_5(struct __block_literal_5 *src) {
688*67e74705SXin Li         //_Block_byref_release(src->byref_obj);
689*67e74705SXin Li         _Block_object_dispose(src->byref_obj, BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK);
690*67e74705SXin Li    }
691*67e74705SXin Li
692*67e74705SXin Li    static struct __block_descriptor_5 {
693*67e74705SXin Li        unsigned long int reserved;
694*67e74705SXin Li        unsigned long int Block_size;
695*67e74705SXin Li        void (*copy_helper)(struct __block_literal_5 *dst, struct __block_literal_5 *src);
696*67e74705SXin Li        void (*dispose_helper)(struct __block_literal_5 *);
697*67e74705SXin Li    } __block_descriptor_5 = { 0, sizeof(struct __block_literal_5), __block_copy_5, __block_dispose_5 };
698*67e74705SXin Li
699*67e74705SXin Liand within the compound statement:
700*67e74705SXin Li
701*67e74705SXin Li.. code-block:: c
702*67e74705SXin Li
703*67e74705SXin Li    truct _block_byref_obj obj = {( .forwarding=&obj, .flags=(1<<25), .size=sizeof(struct _block_byref_obj),
704*67e74705SXin Li                     .byref_keep=_block_byref_obj_keep, .byref_dispose=_block_byref_obj_dispose,
705*67e74705SXin Li                     .captured_obj = <initialization expression> )};
706*67e74705SXin Li
707*67e74705SXin Li    truct __block_literal_5 _block_literal = {
708*67e74705SXin Li         &_NSConcreteStackBlock,
709*67e74705SXin Li         (1<<25)|(1<<29), <uninitialized>,
710*67e74705SXin Li         __block_invoke_5,
711*67e74705SXin Li         &__block_descriptor_5,
712*67e74705SXin Li         &obj,        // a reference to the on-stack structure containing "captured_obj"
713*67e74705SXin Li    };
714*67e74705SXin Li
715*67e74705SXin Li
716*67e74705SXin Li    functioncall(_block_literal->invoke(&_block_literal));
717*67e74705SXin Li
718*67e74705SXin LiC++ Support
719*67e74705SXin Li===========
720*67e74705SXin Li
721*67e74705SXin LiWithin a block stack based C++ objects are copied into ``const`` copies using
722*67e74705SXin Lithe copy constructor.  It is an error if a stack based C++ object is used within
723*67e74705SXin Lia block if it does not have a copy constructor.  In addition both copy and
724*67e74705SXin Lidestroy helper routines must be synthesized for the block to support the
725*67e74705SXin Li``Block_copy()`` operation, and the flags work marked with the (1<<26) bit in
726*67e74705SXin Liaddition to the (1<<25) bit.  The copy helper should call the constructor using
727*67e74705SXin Liappropriate offsets of the variable within the supplied stack based block source
728*67e74705SXin Liand heap based destination for all ``const`` constructed copies, and similarly
729*67e74705SXin Lishould call the destructor in the destroy routine.
730*67e74705SXin Li
731*67e74705SXin LiAs an example, suppose a C++ class ``FOO`` existed with a copy constructor.
732*67e74705SXin LiWithin a code block a stack version of a ``FOO`` object is declared and used
733*67e74705SXin Liwithin a ``Block`` literal expression:
734*67e74705SXin Li
735*67e74705SXin Li.. code-block:: c++
736*67e74705SXin Li
737*67e74705SXin Li    {
738*67e74705SXin Li        FOO foo;
739*67e74705SXin Li        void (^block)(void) = ^{ printf("%d\n", foo.value()); };
740*67e74705SXin Li    }
741*67e74705SXin Li
742*67e74705SXin LiThe compiler would synthesize:
743*67e74705SXin Li
744*67e74705SXin Li.. code-block:: c++
745*67e74705SXin Li
746*67e74705SXin Li    struct __block_literal_10 {
747*67e74705SXin Li        void *isa;
748*67e74705SXin Li        int flags;
749*67e74705SXin Li        int reserved;
750*67e74705SXin Li        void (*invoke)(struct __block_literal_10 *);
751*67e74705SXin Li        struct __block_descriptor_10 *descriptor;
752*67e74705SXin Li        const FOO foo;
753*67e74705SXin Li    };
754*67e74705SXin Li
755*67e74705SXin Li    void __block_invoke_10(struct __block_literal_10 *_block) {
756*67e74705SXin Li       printf("%d\n", _block->foo.value());
757*67e74705SXin Li    }
758*67e74705SXin Li
759*67e74705SXin Li    void __block_literal_10(struct __block_literal_10 *dst, struct __block_literal_10 *src) {
760*67e74705SXin Li         FOO_ctor(&dst->foo, &src->foo);
761*67e74705SXin Li    }
762*67e74705SXin Li
763*67e74705SXin Li    void __block_dispose_10(struct __block_literal_10 *src) {
764*67e74705SXin Li         FOO_dtor(&src->foo);
765*67e74705SXin Li    }
766*67e74705SXin Li
767*67e74705SXin Li    static struct __block_descriptor_10 {
768*67e74705SXin Li        unsigned long int reserved;
769*67e74705SXin Li        unsigned long int Block_size;
770*67e74705SXin Li        void (*copy_helper)(struct __block_literal_10 *dst, struct __block_literal_10 *src);
771*67e74705SXin Li        void (*dispose_helper)(struct __block_literal_10 *);
772*67e74705SXin Li    } __block_descriptor_10 = { 0, sizeof(struct __block_literal_10), __block_copy_10, __block_dispose_10 };
773*67e74705SXin Li
774*67e74705SXin Liand the code would be:
775*67e74705SXin Li
776*67e74705SXin Li.. code-block:: c++
777*67e74705SXin Li
778*67e74705SXin Li    {
779*67e74705SXin Li      FOO foo;
780*67e74705SXin Li      comp_ctor(&foo); // default constructor
781*67e74705SXin Li      struct __block_literal_10 _block_literal = {
782*67e74705SXin Li        &_NSConcreteStackBlock,
783*67e74705SXin Li        (1<<25)|(1<<26)|(1<<29), <uninitialized>,
784*67e74705SXin Li        __block_invoke_10,
785*67e74705SXin Li        &__block_descriptor_10,
786*67e74705SXin Li       };
787*67e74705SXin Li       comp_ctor(&_block_literal->foo, &foo);  // const copy into stack version
788*67e74705SXin Li       struct __block_literal_10 &block = &_block_literal;  // assign literal to block variable
789*67e74705SXin Li       block->invoke(block);    // invoke block
790*67e74705SXin Li       comp_dtor(&_block_literal->foo); // destroy stack version of const block copy
791*67e74705SXin Li       comp_dtor(&foo); // destroy original version
792*67e74705SXin Li    }
793*67e74705SXin Li
794*67e74705SXin Li
795*67e74705SXin LiC++ objects stored in ``__block`` storage start out on the stack in a
796*67e74705SXin Li``block_byref`` data structure as do other variables.  Such objects (if not
797*67e74705SXin Li``const`` objects) must support a regular copy constructor.  The ``block_byref``
798*67e74705SXin Lidata structure will have copy and destroy helper routines synthesized by the
799*67e74705SXin Licompiler.  The copy helper will have code created to perform the copy
800*67e74705SXin Liconstructor based on the initial stack ``block_byref`` data structure, and will
801*67e74705SXin Lialso set the (1<<26) bit in addition to the (1<<25) bit.  The destroy helper
802*67e74705SXin Liwill have code to do the destructor on the object stored within the supplied
803*67e74705SXin Li``block_byref`` heap data structure.  For example,
804*67e74705SXin Li
805*67e74705SXin Li.. code-block:: c++
806*67e74705SXin Li
807*67e74705SXin Li    __block FOO blockStorageFoo;
808*67e74705SXin Li
809*67e74705SXin Lirequires the normal constructor for the embedded ``blockStorageFoo`` object:
810*67e74705SXin Li
811*67e74705SXin Li.. code-block:: c++
812*67e74705SXin Li
813*67e74705SXin Li    FOO_ctor(& _block_byref_blockStorageFoo->blockStorageFoo);
814*67e74705SXin Li
815*67e74705SXin Liand at scope termination the destructor:
816*67e74705SXin Li
817*67e74705SXin Li.. code-block:: c++
818*67e74705SXin Li
819*67e74705SXin Li    FOO_dtor(& _block_byref_blockStorageFoo->blockStorageFoo);
820*67e74705SXin Li
821*67e74705SXin LiNote that the forwarding indirection is *NOT* used.
822*67e74705SXin Li
823*67e74705SXin LiThe compiler would need to generate (if used from a block literal) the following
824*67e74705SXin Licopy/dispose helpers:
825*67e74705SXin Li
826*67e74705SXin Li.. code-block:: c++
827*67e74705SXin Li
828*67e74705SXin Li    void _block_byref_obj_keep(struct _block_byref_blockStorageFoo *dst, struct _block_byref_blockStorageFoo *src) {
829*67e74705SXin Li         FOO_ctor(&dst->blockStorageFoo, &src->blockStorageFoo);
830*67e74705SXin Li    }
831*67e74705SXin Li
832*67e74705SXin Li    void _block_byref_obj_dispose(struct _block_byref_blockStorageFoo *src) {
833*67e74705SXin Li         FOO_dtor(&src->blockStorageFoo);
834*67e74705SXin Li    }
835*67e74705SXin Li
836*67e74705SXin Lifor the appropriately named constructor and destructor for the class/struct
837*67e74705SXin Li``FOO``.
838*67e74705SXin Li
839*67e74705SXin LiTo support member variable and function access the compiler will synthesize a
840*67e74705SXin Li``const`` pointer to a block version of the ``this`` pointer.
841*67e74705SXin Li
842*67e74705SXin Li.. _RuntimeHelperFunctions:
843*67e74705SXin Li
844*67e74705SXin LiRuntime Helper Functions
845*67e74705SXin Li========================
846*67e74705SXin Li
847*67e74705SXin LiThe runtime helper functions are described in
848*67e74705SXin Li``/usr/local/include/Block_private.h``.  To summarize their use, a ``Block``
849*67e74705SXin Lirequires copy/dispose helpers if it imports any block variables, ``__block``
850*67e74705SXin Listorage variables, ``__attribute__((NSObject))`` variables, or C++ ``const``
851*67e74705SXin Licopied objects with constructor/destructors.  The (1<<26) bit is set and
852*67e74705SXin Lifunctions are generated.
853*67e74705SXin Li
854*67e74705SXin LiThe block copy helper function should, for each of the variables of the type
855*67e74705SXin Limentioned above, call:
856*67e74705SXin Li
857*67e74705SXin Li.. code-block:: c
858*67e74705SXin Li
859*67e74705SXin Li     _Block_object_assign(&dst->target, src->target, BLOCK_FIELD_<appropo>);
860*67e74705SXin Li
861*67e74705SXin Liin the copy helper and:
862*67e74705SXin Li
863*67e74705SXin Li.. code-block:: c
864*67e74705SXin Li
865*67e74705SXin Li    _Block_object_dispose(->target, BLOCK_FIELD_<appropo>);
866*67e74705SXin Li
867*67e74705SXin Liin the dispose helper where ``<appropo>`` is:
868*67e74705SXin Li
869*67e74705SXin Li.. code-block:: c
870*67e74705SXin Li
871*67e74705SXin Li    enum {
872*67e74705SXin Li        BLOCK_FIELD_IS_OBJECT   =  3,  // id, NSObject, __attribute__((NSObject)), block, ...
873*67e74705SXin Li        BLOCK_FIELD_IS_BLOCK    =  7,  // a block variable
874*67e74705SXin Li        BLOCK_FIELD_IS_BYREF    =  8,  // the on stack structure holding the __block variable
875*67e74705SXin Li
876*67e74705SXin Li        BLOCK_FIELD_IS_WEAK     = 16,  // declared __weak
877*67e74705SXin Li
878*67e74705SXin Li        BLOCK_BYREF_CALLER      = 128, // called from byref copy/dispose helpers
879*67e74705SXin Li    };
880*67e74705SXin Li
881*67e74705SXin Liand of course the constructors/destructors for ``const`` copied C++ objects.
882*67e74705SXin Li
883*67e74705SXin LiThe ``block_byref`` data structure similarly requires copy/dispose helpers for
884*67e74705SXin Liblock variables, ``__attribute__((NSObject))`` variables, or C++ ``const``
885*67e74705SXin Licopied objects with constructor/destructors, and again the (1<<26) bit is set
886*67e74705SXin Liand functions are generated in the same manner.
887*67e74705SXin Li
888*67e74705SXin LiUnder ObjC we allow ``__weak`` as an attribute on ``__block`` variables, and
889*67e74705SXin Lithis causes the addition of ``BLOCK_FIELD_IS_WEAK`` orred onto the
890*67e74705SXin Li``BLOCK_FIELD_IS_BYREF`` flag when copying the ``block_byref`` structure in the
891*67e74705SXin Li``Block`` copy helper, and onto the ``BLOCK_FIELD_<appropo>`` field within the
892*67e74705SXin Li``block_byref`` copy/dispose helper calls.
893*67e74705SXin Li
894*67e74705SXin LiThe prototypes, and summary, of the helper functions are:
895*67e74705SXin Li
896*67e74705SXin Li.. code-block:: c
897*67e74705SXin Li
898*67e74705SXin Li    /* Certain field types require runtime assistance when being copied to the
899*67e74705SXin Li       heap.  The following function is used to copy fields of types: blocks,
900*67e74705SXin Li       pointers to byref structures, and objects (including
901*67e74705SXin Li       __attribute__((NSObject)) pointers.  BLOCK_FIELD_IS_WEAK is orthogonal to
902*67e74705SXin Li       the other choices which are mutually exclusive.  Only in a Block copy
903*67e74705SXin Li       helper will one see BLOCK_FIELD_IS_BYREF.
904*67e74705SXin Li    */
905*67e74705SXin Li    void _Block_object_assign(void *destAddr, const void *object, const int flags);
906*67e74705SXin Li
907*67e74705SXin Li    /* Similarly a compiler generated dispose helper needs to call back for each
908*67e74705SXin Li       field of the byref data structure.  (Currently the implementation only
909*67e74705SXin Li       packs one field into the byref structure but in principle there could be
910*67e74705SXin Li       more).  The same flags used in the copy helper should be used for each
911*67e74705SXin Li       call generated to this function:
912*67e74705SXin Li    */
913*67e74705SXin Li    void _Block_object_dispose(const void *object, const int flags);
914*67e74705SXin Li
915*67e74705SXin LiCopyright
916*67e74705SXin Li=========
917*67e74705SXin Li
918*67e74705SXin LiCopyright 2008-2010 Apple, Inc.
919*67e74705SXin LiPermission is hereby granted, free of charge, to any person obtaining a copy
920*67e74705SXin Liof this software and associated documentation files (the "Software"), to deal
921*67e74705SXin Liin the Software without restriction, including without limitation the rights
922*67e74705SXin Lito use, copy, modify, merge, publish, distribute, sublicense, and/or sell
923*67e74705SXin Licopies of the Software, and to permit persons to whom the Software is
924*67e74705SXin Lifurnished to do so, subject to the following conditions:
925*67e74705SXin Li
926*67e74705SXin LiThe above copyright notice and this permission notice shall be included in
927*67e74705SXin Liall copies or substantial portions of the Software.
928*67e74705SXin Li
929*67e74705SXin LiTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
930*67e74705SXin LiIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
931*67e74705SXin LiFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
932*67e74705SXin LiAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
933*67e74705SXin LiLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
934*67e74705SXin LiOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
935*67e74705SXin LiTHE SOFTWARE.
936