1/*
2 * Block_private.h
3 *
4 * SPI for Blocks
5 *
6 * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
7 *
8 * @APPLE_LLVM_LICENSE_HEADER@
9 *
10 */
11
12#ifndef _BLOCK_PRIVATE_H_
13#define _BLOCK_PRIVATE_H_
14
15#include <Availability.h>
16#include <AvailabilityMacros.h>
17#include <TargetConditionals.h>
18
19#include <stdbool.h>
20#include <stdint.h>
21#include <stdio.h>
22
23#include <Block.h>
24
25#if __cplusplus
26extern "C" {
27#endif
28
29
30// Values for Block_layout->flags to describe block objects
31enum {
32    BLOCK_DEALLOCATING =      (0x0001),  // runtime
33    BLOCK_REFCOUNT_MASK =     (0xfffe),  // runtime
34    BLOCK_NEEDS_FREE =        (1 << 24), // runtime
35    BLOCK_HAS_COPY_DISPOSE =  (1 << 25), // compiler
36    BLOCK_HAS_CTOR =          (1 << 26), // compiler: helpers have C++ code
37    BLOCK_IS_GC =             (1 << 27), // runtime
38    BLOCK_IS_GLOBAL =         (1 << 28), // compiler
39    BLOCK_USE_STRET =         (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
40    BLOCK_HAS_SIGNATURE  =    (1 << 30), // compiler
41    BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31)  // compiler
42};
43
44#define BLOCK_DESCRIPTOR_1 1
45struct Block_descriptor_1 {
46    uintptr_t reserved;
47    uintptr_t size;
48};
49
50#define BLOCK_DESCRIPTOR_2 1
51struct Block_descriptor_2 {
52    // requires BLOCK_HAS_COPY_DISPOSE
53    void (*copy)(void *dst, const void *src);
54    void (*dispose)(const void *);
55};
56
57#define BLOCK_DESCRIPTOR_3 1
58struct Block_descriptor_3 {
59    // requires BLOCK_HAS_SIGNATURE
60    const char *signature;
61    const char *layout;     // contents depend on BLOCK_HAS_EXTENDED_LAYOUT
62};
63
64struct Block_layout {
65    void *isa;
66    volatile int32_t flags; // contains ref count
67    int32_t reserved;
68    void (*invoke)(void *, ...);
69    struct Block_descriptor_1 *descriptor;
70    // imported variables
71};
72
73
74// Values for Block_byref->flags to describe __block variables
75enum {
76    // Byref refcount must use the same bits as Block_layout's refcount.
77    // BLOCK_DEALLOCATING =      (0x0001),  // runtime
78    // BLOCK_REFCOUNT_MASK =     (0xfffe),  // runtime
79
80    BLOCK_BYREF_LAYOUT_MASK =       (0xf << 28), // compiler
81    BLOCK_BYREF_LAYOUT_EXTENDED =   (  1 << 28), // compiler
82    BLOCK_BYREF_LAYOUT_NON_OBJECT = (  2 << 28), // compiler
83    BLOCK_BYREF_LAYOUT_STRONG =     (  3 << 28), // compiler
84    BLOCK_BYREF_LAYOUT_WEAK =       (  4 << 28), // compiler
85    BLOCK_BYREF_LAYOUT_UNRETAINED = (  5 << 28), // compiler
86
87    BLOCK_BYREF_IS_GC =             (  1 << 27), // runtime
88
89    BLOCK_BYREF_HAS_COPY_DISPOSE =  (  1 << 25), // compiler
90    BLOCK_BYREF_NEEDS_FREE =        (  1 << 24), // runtime
91};
92
93struct Block_byref {
94    void *isa;
95    struct Block_byref *forwarding;
96    volatile int32_t flags; // contains ref count
97    uint32_t size;
98};
99
100struct Block_byref_2 {
101    // requires BLOCK_BYREF_HAS_COPY_DISPOSE
102    void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
103    void (*byref_destroy)(struct Block_byref *);
104};
105
106struct Block_byref_3 {
107    // requires BLOCK_BYREF_LAYOUT_EXTENDED
108    const char *layout;
109};
110
111
112// Extended layout encoding.
113
114// Values for Block_descriptor_3->layout with BLOCK_HAS_EXTENDED_LAYOUT
115// and for Block_byref_3->layout with BLOCK_BYREF_LAYOUT_EXTENDED
116
117// If the layout field is less than 0x1000, then it is a compact encoding
118// of the form 0xXYZ: X strong pointers, then Y byref pointers,
119// then Z weak pointers.
120
121// If the layout field is 0x1000 or greater, it points to a
122// string of layout bytes. Each byte is of the form 0xPN.
123// Operator P is from the list below. Value N is a parameter for the operator.
124// Byte 0x00 terminates the layout; remaining block data is non-pointer bytes.
125
126enum {
127    BLOCK_LAYOUT_ESCAPE = 0, // N=0 halt, rest is non-pointer. N!=0 reserved.
128    BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,    // N bytes non-objects
129    BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,    // N words non-objects
130    BLOCK_LAYOUT_STRONG           = 3,    // N words strong pointers
131    BLOCK_LAYOUT_BYREF            = 4,    // N words byref pointers
132    BLOCK_LAYOUT_WEAK             = 5,    // N words weak pointers
133    BLOCK_LAYOUT_UNRETAINED       = 6,    // N words unretained pointers
134    BLOCK_LAYOUT_UNKNOWN_WORDS_7  = 7,    // N words, reserved
135    BLOCK_LAYOUT_UNKNOWN_WORDS_8  = 8,    // N words, reserved
136    BLOCK_LAYOUT_UNKNOWN_WORDS_9  = 9,    // N words, reserved
137    BLOCK_LAYOUT_UNKNOWN_WORDS_A  = 0xA,  // N words, reserved
138    BLOCK_LAYOUT_UNUSED_B         = 0xB,  // unspecified, reserved
139    BLOCK_LAYOUT_UNUSED_C         = 0xC,  // unspecified, reserved
140    BLOCK_LAYOUT_UNUSED_D         = 0xD,  // unspecified, reserved
141    BLOCK_LAYOUT_UNUSED_E         = 0xE,  // unspecified, reserved
142    BLOCK_LAYOUT_UNUSED_F         = 0xF,  // unspecified, reserved
143};
144
145
146// Runtime support functions used by compiler when generating copy/dispose helpers
147
148// Values for _Block_object_assign() and _Block_object_dispose() parameters
149enum {
150    // see function implementation for a more complete description of these fields and combinations
151    BLOCK_FIELD_IS_OBJECT   =  3,  // id, NSObject, __attribute__((NSObject)), block, ...
152    BLOCK_FIELD_IS_BLOCK    =  7,  // a block variable
153    BLOCK_FIELD_IS_BYREF    =  8,  // the on stack structure holding the __block variable
154    BLOCK_FIELD_IS_WEAK     = 16,  // declared __weak, only used in byref copy helpers
155    BLOCK_BYREF_CALLER      = 128, // called from __block (byref) copy/dispose support routines.
156};
157
158enum {
159    BLOCK_ALL_COPY_DISPOSE_FLAGS =
160        BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_BYREF |
161        BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER
162};
163
164// Runtime entry point called by compiler when assigning objects inside copy helper routines
165BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
166    // BLOCK_FIELD_IS_BYREF is only used from within block copy helpers
167
168
169// runtime entry point called by the compiler when disposing of objects inside dispose helper routine
170BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
171
172
173// Other support functions
174
175// runtime entry to get total size of a closure
176BLOCK_EXPORT size_t Block_size(void *aBlock);
177
178// indicates whether block was compiled with compiler that sets the ABI related metadata bits
179BLOCK_EXPORT bool _Block_has_signature(void *aBlock)
180    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
181
182// returns TRUE if return value of block is on the stack, FALSE otherwise
183BLOCK_EXPORT bool _Block_use_stret(void *aBlock)
184    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
185
186// Returns a string describing the block's parameter and return types.
187// The encoding scheme is the same as Objective-C @encode.
188// Returns NULL for blocks compiled with some compilers.
189BLOCK_EXPORT const char * _Block_signature(void *aBlock)
190    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
191
192// Returns a string describing the block's GC layout.
193// This uses the GC skip/scan encoding.
194// May return NULL.
195BLOCK_EXPORT const char * _Block_layout(void *aBlock)
196    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
197
198// Returns a string describing the block's layout.
199// This uses the "extended layout" form described above.
200// May return NULL.
201BLOCK_EXPORT const char * _Block_extended_layout(void *aBlock)
202    __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_7_0);
203
204// Callable only from the ARR weak subsystem while in exclusion zone
205BLOCK_EXPORT bool _Block_tryRetain(const void *aBlock)
206    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
207
208// Callable only from the ARR weak subsystem while in exclusion zone
209BLOCK_EXPORT bool _Block_isDeallocating(const void *aBlock)
210    __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
211
212
213// the raw data space for runtime classes for blocks
214// class+meta used for stack, malloc, and collectable based blocks
215BLOCK_EXPORT void * _NSConcreteMallocBlock[32]
216    __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
217BLOCK_EXPORT void * _NSConcreteAutoBlock[32]
218    __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
219BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32]
220    __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
221BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32]
222    __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
223// declared in Block.h
224// BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
225// BLOCK_EXPORT void * _NSConcreteStackBlock[32];
226
227
228// the intercept routines that must be used under GC
229BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
230                                  void (*setHasRefcount)(const void *, const bool),
231                                  void (*gc_assign_strong)(void *, void **),
232                                  void (*gc_assign_weak)(const void *, void *),
233                                  void (*gc_memmove)(void *, void *, unsigned long));
234
235// earlier version, now simply transitional
236BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
237                                  void (*setHasRefcount)(const void *, const bool),
238                                  void (*gc_assign_strong)(void *, void **),
239                                  void (*gc_assign_weak)(const void *, void *));
240
241BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
242                                 void (*release)(const void *));
243
244struct Block_callbacks_RR {
245    size_t  size;                   // size == sizeof(struct Block_callbacks_RR)
246    void  (*retain)(const void *);
247    void  (*release)(const void *);
248    void  (*destructInstance)(const void *);
249};
250typedef struct Block_callbacks_RR Block_callbacks_RR;
251
252BLOCK_EXPORT void _Block_use_RR2(const Block_callbacks_RR *callbacks);
253
254// make a collectable GC heap based Block.  Not useful under non-GC.
255BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
256
257// thread-unsafe diagnostic
258BLOCK_EXPORT const char *_Block_dump(const void *block);
259
260
261// Obsolete
262
263// first layout
264struct Block_basic {
265    void *isa;
266    int Block_flags;  // int32_t
267    int Block_size; // XXX should be packed into Block_flags
268    void (*Block_invoke)(void *);
269    void (*Block_copy)(void *dst, void *src);  // iff BLOCK_HAS_COPY_DISPOSE
270    void (*Block_dispose)(void *);             // iff BLOCK_HAS_COPY_DISPOSE
271    //long params[0];  // where const imports, __block storage references, etc. get laid down
272} __attribute__((deprecated));
273
274
275#if __cplusplus
276}
277#endif
278
279
280#endif
281