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