xref: /llvm-project/compiler-rt/lib/BlocksRuntime/Block_private.h (revision 1dbb7578fffa65ab1ee52be04b1ed30f530d8b0a)
1*b8665226SAlexey Samsonov /*
2*b8665226SAlexey Samsonov  * Block_private.h
3*b8665226SAlexey Samsonov  *
4*b8665226SAlexey Samsonov  * Copyright 2008-2010 Apple, Inc. Permission is hereby granted, free of charge,
5*b8665226SAlexey Samsonov  * to any person obtaining a copy of this software and associated documentation
6*b8665226SAlexey Samsonov  * files (the "Software"), to deal in the Software without restriction,
7*b8665226SAlexey Samsonov  * including without limitation the rights to use, copy, modify, merge, publish,
8*b8665226SAlexey Samsonov  * distribute, sublicense, and/or sell copies of the Software, and to permit
9*b8665226SAlexey Samsonov  * persons to whom the Software is furnished to do so, subject to the following
10*b8665226SAlexey Samsonov  * conditions:
11*b8665226SAlexey Samsonov  *
12*b8665226SAlexey Samsonov  * The above copyright notice and this permission notice shall be included in
13*b8665226SAlexey Samsonov  * all copies or substantial portions of the Software.
14*b8665226SAlexey Samsonov  *
15*b8665226SAlexey Samsonov  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*b8665226SAlexey Samsonov  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*b8665226SAlexey Samsonov  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18*b8665226SAlexey Samsonov  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*b8665226SAlexey Samsonov  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*b8665226SAlexey Samsonov  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*b8665226SAlexey Samsonov  * SOFTWARE.
22*b8665226SAlexey Samsonov  *
23*b8665226SAlexey Samsonov  */
24*b8665226SAlexey Samsonov 
25*b8665226SAlexey Samsonov #ifndef _BLOCK_PRIVATE_H_
26*b8665226SAlexey Samsonov #define _BLOCK_PRIVATE_H_
27*b8665226SAlexey Samsonov 
28*b8665226SAlexey Samsonov #if !defined(BLOCK_EXPORT)
29*b8665226SAlexey Samsonov #   if defined(__cplusplus)
30*b8665226SAlexey Samsonov #       define BLOCK_EXPORT extern "C"
31*b8665226SAlexey Samsonov #   else
32*b8665226SAlexey Samsonov #       define BLOCK_EXPORT extern
33*b8665226SAlexey Samsonov #   endif
34*b8665226SAlexey Samsonov #endif
35*b8665226SAlexey Samsonov 
36*b8665226SAlexey Samsonov #ifndef _MSC_VER
37*b8665226SAlexey Samsonov #include <stdbool.h>
38*b8665226SAlexey Samsonov #else
39*b8665226SAlexey Samsonov /* MSVC doesn't have <stdbool.h>. Compensate. */
40*b8665226SAlexey Samsonov typedef char bool;
41*b8665226SAlexey Samsonov #define true (bool)1
42*b8665226SAlexey Samsonov #define false (bool)0
43*b8665226SAlexey Samsonov #endif
44*b8665226SAlexey Samsonov 
45*b8665226SAlexey Samsonov #if defined(__cplusplus)
46*b8665226SAlexey Samsonov extern "C" {
47*b8665226SAlexey Samsonov #endif
48*b8665226SAlexey Samsonov 
49*b8665226SAlexey Samsonov 
50*b8665226SAlexey Samsonov enum {
51*b8665226SAlexey Samsonov     BLOCK_REFCOUNT_MASK =     (0xffff),
52*b8665226SAlexey Samsonov     BLOCK_NEEDS_FREE =        (1 << 24),
53*b8665226SAlexey Samsonov     BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
54*b8665226SAlexey Samsonov     BLOCK_HAS_CTOR =          (1 << 26), /* Helpers have C++ code. */
55*b8665226SAlexey Samsonov     BLOCK_IS_GC =             (1 << 27),
56*b8665226SAlexey Samsonov     BLOCK_IS_GLOBAL =         (1 << 28),
57*b8665226SAlexey Samsonov     BLOCK_HAS_DESCRIPTOR =    (1 << 29)
58*b8665226SAlexey Samsonov };
59*b8665226SAlexey Samsonov 
60*b8665226SAlexey Samsonov 
61*b8665226SAlexey Samsonov /* Revised new layout. */
62*b8665226SAlexey Samsonov struct Block_descriptor {
63*b8665226SAlexey Samsonov     unsigned long int reserved;
64*b8665226SAlexey Samsonov     unsigned long int size;
65*b8665226SAlexey Samsonov     void (*copy)(void *dst, void *src);
66*b8665226SAlexey Samsonov     void (*dispose)(void *);
67*b8665226SAlexey Samsonov };
68*b8665226SAlexey Samsonov 
69*b8665226SAlexey Samsonov 
70*b8665226SAlexey Samsonov struct Block_layout {
71*b8665226SAlexey Samsonov     void *isa;
72*b8665226SAlexey Samsonov     int flags;
73*b8665226SAlexey Samsonov     int reserved;
74*b8665226SAlexey Samsonov     void (*invoke)(void *, ...);
75*b8665226SAlexey Samsonov     struct Block_descriptor *descriptor;
76*b8665226SAlexey Samsonov     /* Imported variables. */
77*b8665226SAlexey Samsonov };
78*b8665226SAlexey Samsonov 
79*b8665226SAlexey Samsonov 
80*b8665226SAlexey Samsonov struct Block_byref {
81*b8665226SAlexey Samsonov     void *isa;
82*b8665226SAlexey Samsonov     struct Block_byref *forwarding;
83*b8665226SAlexey Samsonov     int flags; /* refcount; */
84*b8665226SAlexey Samsonov     int size;
85*b8665226SAlexey Samsonov     void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
86*b8665226SAlexey Samsonov     void (*byref_destroy)(struct Block_byref *);
87*b8665226SAlexey Samsonov     /* long shared[0]; */
88*b8665226SAlexey Samsonov };
89*b8665226SAlexey Samsonov 
90*b8665226SAlexey Samsonov 
91*b8665226SAlexey Samsonov struct Block_byref_header {
92*b8665226SAlexey Samsonov     void *isa;
93*b8665226SAlexey Samsonov     struct Block_byref *forwarding;
94*b8665226SAlexey Samsonov     int flags;
95*b8665226SAlexey Samsonov     int size;
96*b8665226SAlexey Samsonov };
97*b8665226SAlexey Samsonov 
98*b8665226SAlexey Samsonov 
99*b8665226SAlexey Samsonov /* Runtime support functions used by compiler when generating copy/dispose helpers. */
100*b8665226SAlexey Samsonov 
101*b8665226SAlexey Samsonov enum {
102*b8665226SAlexey Samsonov     /* See function implementation for a more complete description of these fields and combinations */
103*b8665226SAlexey Samsonov     BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)), block, ... */
104*b8665226SAlexey Samsonov     BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
105*b8665226SAlexey Samsonov     BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block variable */
106*b8665226SAlexey Samsonov     BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy helpers */
107*b8665226SAlexey Samsonov     BLOCK_BYREF_CALLER      = 128  /* called from __block (byref) copy/dispose support routines. */
108*b8665226SAlexey Samsonov };
109*b8665226SAlexey Samsonov 
110*b8665226SAlexey Samsonov /* Runtime entry point called by compiler when assigning objects inside copy helper routines */
111*b8665226SAlexey Samsonov BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
112*b8665226SAlexey Samsonov     /* BLOCK_FIELD_IS_BYREF is only used from within block copy helpers */
113*b8665226SAlexey Samsonov 
114*b8665226SAlexey Samsonov 
115*b8665226SAlexey Samsonov /* runtime entry point called by the compiler when disposing of objects inside dispose helper routine */
116*b8665226SAlexey Samsonov BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
117*b8665226SAlexey Samsonov 
118*b8665226SAlexey Samsonov 
119*b8665226SAlexey Samsonov 
120*b8665226SAlexey Samsonov /* Other support functions */
121*b8665226SAlexey Samsonov 
122*b8665226SAlexey Samsonov /* Runtime entry to get total size of a closure */
123*b8665226SAlexey Samsonov BLOCK_EXPORT unsigned long int Block_size(void *block_basic);
124*b8665226SAlexey Samsonov 
125*b8665226SAlexey Samsonov 
126*b8665226SAlexey Samsonov 
127*b8665226SAlexey Samsonov /* the raw data space for runtime classes for blocks */
128*b8665226SAlexey Samsonov /* class+meta used for stack, malloc, and collectable based blocks */
129*b8665226SAlexey Samsonov BLOCK_EXPORT void * _NSConcreteStackBlock[32];
130*b8665226SAlexey Samsonov BLOCK_EXPORT void * _NSConcreteMallocBlock[32];
131*b8665226SAlexey Samsonov BLOCK_EXPORT void * _NSConcreteAutoBlock[32];
132*b8665226SAlexey Samsonov BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];
133*b8665226SAlexey Samsonov BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
134*b8665226SAlexey Samsonov BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];
135*b8665226SAlexey Samsonov 
136*b8665226SAlexey Samsonov 
137*b8665226SAlexey Samsonov /* the intercept routines that must be used under GC */
138*b8665226SAlexey Samsonov BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
139*b8665226SAlexey Samsonov                                   void (*setHasRefcount)(const void *, const bool),
140*b8665226SAlexey Samsonov                                   void (*gc_assign_strong)(void *, void **),
141*b8665226SAlexey Samsonov                                   void (*gc_assign_weak)(const void *, void *),
142*b8665226SAlexey Samsonov                                   void (*gc_memmove)(void *, void *, unsigned long));
143*b8665226SAlexey Samsonov 
144*b8665226SAlexey Samsonov /* earlier version, now simply transitional */
145*b8665226SAlexey Samsonov BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
146*b8665226SAlexey Samsonov                                   void (*setHasRefcount)(const void *, const bool),
147*b8665226SAlexey Samsonov                                   void (*gc_assign_strong)(void *, void **),
148*b8665226SAlexey Samsonov                                   void (*gc_assign_weak)(const void *, void *));
149*b8665226SAlexey Samsonov 
150*b8665226SAlexey Samsonov BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
151*b8665226SAlexey Samsonov                                  void (*release)(const void *));
152*b8665226SAlexey Samsonov 
153*b8665226SAlexey Samsonov /* make a collectable GC heap based Block.  Not useful under non-GC. */
154*b8665226SAlexey Samsonov BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
155*b8665226SAlexey Samsonov 
156*b8665226SAlexey Samsonov /* thread-unsafe diagnostic */
157*b8665226SAlexey Samsonov BLOCK_EXPORT const char *_Block_dump(const void *block);
158*b8665226SAlexey Samsonov 
159*b8665226SAlexey Samsonov 
160*b8665226SAlexey Samsonov /* Obsolete */
161*b8665226SAlexey Samsonov 
162*b8665226SAlexey Samsonov /* first layout */
163*b8665226SAlexey Samsonov struct Block_basic {
164*b8665226SAlexey Samsonov     void *isa;
165*b8665226SAlexey Samsonov     int Block_flags;  /* int32_t */
166*b8665226SAlexey Samsonov     int Block_size;  /* XXX should be packed into Block_flags */
167*b8665226SAlexey Samsonov     void (*Block_invoke)(void *);
168*b8665226SAlexey Samsonov     void (*Block_copy)(void *dst, void *src);  /* iff BLOCK_HAS_COPY_DISPOSE */
169*b8665226SAlexey Samsonov     void (*Block_dispose)(void *);             /* iff BLOCK_HAS_COPY_DISPOSE */
170*b8665226SAlexey Samsonov     /* long params[0];  // where const imports, __block storage references, etc. get laid down */
171*b8665226SAlexey Samsonov };
172*b8665226SAlexey Samsonov 
173*b8665226SAlexey Samsonov 
174*b8665226SAlexey Samsonov #if defined(__cplusplus)
175*b8665226SAlexey Samsonov }
176*b8665226SAlexey Samsonov #endif
177*b8665226SAlexey Samsonov 
178*b8665226SAlexey Samsonov 
179*b8665226SAlexey Samsonov #endif /* _BLOCK_PRIVATE_H_ */
180