]> git.ipfire.org Git - thirdparty/gcc.git/blame - libobjc/gc.c
Fix boostrap failure in tree-ssa-loop-ch.cc
[thirdparty/gcc.git] / libobjc / gc.c
CommitLineData
88e17b57 1/* Basic data types for Objective C.
83ffe9cd 2 Copyright (C) 1998-2023 Free Software Foundation, Inc.
88e17b57
BE
3 Contributed by Ovidiu Predescu.
4
6c82ad25 5This file is part of GCC.
88e17b57 6
6c82ad25 7GCC is free software; you can redistribute it and/or modify
88e17b57 8it under the terms of the GNU General Public License as published by
748086b7 9the Free Software Foundation; either version 3, or (at your option)
88e17b57
BE
10any later version.
11
6c82ad25 12GCC is distributed in the hope that it will be useful,
88e17b57
BE
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
748086b7
JJ
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
88e17b57 20
748086b7
JJ
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
88e17b57 25
6dead247 26#include "objc-private/common.h"
348a3445 27#include "objc/objc.h"
88e17b57 28
718a8e53
NP
29#if OBJC_WITH_GC
30
31#include "tconfig.h"
88e17b57 32#include <assert.h>
80e4b9e5 33#include <ctype.h> /* For isdigit. */
88e17b57 34#include <string.h>
63b6f9ea 35#include <stdlib.h>
80e4b9e5
NP
36#include "objc/runtime.h"
37#include "objc-private/module-abi-8.h"
88e17b57 38
114bf3f1 39#include <gc/gc.h>
63b6f9ea 40#include <limits.h>
88e17b57
BE
41
42/* gc_typed.h uses the following but doesn't declare them */
43typedef GC_word word;
44typedef GC_signed_word signed_word;
63b6f9ea 45#define BITS_PER_WORD (CHAR_BIT * sizeof (word))
88e17b57 46
114bf3f1 47#include <gc/gc_typed.h>
88e17b57
BE
48
49/* The following functions set up in `mask` the corresponding pointers.
50 The offset is incremented with the size of the type. */
51
52#define ROUND(V, A) \
40165636
RB
53 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
54 __a * ((__v+__a - 1)/__a); })
88e17b57
BE
55
56#define SET_BIT_FOR_OFFSET(mask, offset) \
40165636 57 GC_set_bit (mask, offset / sizeof (void *))
88e17b57
BE
58
59/* Some prototypes */
60static void
61__objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
62static void
63__objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
64
65
66static void
67__objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
68{
40165636 69 int i, len = atoi (type + 1);
88e17b57 70
40165636 71 while (isdigit (*++type))
88e17b57
BE
72 /* do nothing */; /* skip the size of the array */
73
74 switch (*type) {
75 case _C_ARY_B:
76 for (i = 0; i < len; i++)
77 __objc_gc_setup_array (mask, type, offset);
78 break;
79
80 case _C_STRUCT_B:
81 for (i = 0; i < len; i++)
82 __objc_gc_setup_struct (mask, type, offset);
83 break;
84
85 case _C_UNION_B:
86 for (i = 0; i < len; i++)
87 __objc_gc_setup_union (mask, type, offset);
88 break;
89
90 default:
91 break;
92 }
93}
94
95static void
96__objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
97{
98 struct objc_struct_layout layout;
99 unsigned int position;
100 const char *mtype;
101
102 objc_layout_structure (type, &layout);
103
104 while (objc_layout_structure_next_member (&layout))
105 {
106 BOOL gc_invisible = NO;
107
108 objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
109
110 /* Skip the variable name */
111 if (*mtype == '"')
112 {
113 for (mtype++; *mtype++ != '"';)
114 /* do nothing */;
115 }
116
117 if (*mtype == _C_GCINVISIBLE)
118 {
119 gc_invisible = YES;
120 mtype++;
121 }
122
123 /* Add to position the offset of this structure */
124 position += offset;
125
126 switch (*mtype) {
127 case _C_ID:
128 case _C_CLASS:
129 case _C_SEL:
130 case _C_PTR:
131 case _C_CHARPTR:
132 case _C_ATOM:
40165636
RB
133 if (! gc_invisible)
134 SET_BIT_FOR_OFFSET (mask, position);
88e17b57
BE
135 break;
136
137 case _C_ARY_B:
138 __objc_gc_setup_array (mask, mtype, position);
139 break;
140
141 case _C_STRUCT_B:
142 __objc_gc_setup_struct (mask, mtype, position);
143 break;
144
145 case _C_UNION_B:
146 __objc_gc_setup_union (mask, mtype, position);
147 break;
148
149 default:
150 break;
151 }
152 }
153}
154
155static void
156__objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
157{
158 /* Sub-optimal, quick implementation: assume the union is made of
159 pointers, set up the mask accordingly. */
160
161 int i, size, align;
162
163 /* Skip the variable name */
164 if (*type == '"')
165 {
166 for (type++; *type++ != '"';)
167 /* do nothing */;
168 }
169
170 size = objc_sizeof_type (type);
171 align = objc_alignof_type (type);
172
40165636
RB
173 offset = ROUND (offset, align);
174 for (i = 0; i < size; i += sizeof (void *))
88e17b57 175 {
40165636
RB
176 SET_BIT_FOR_OFFSET (mask, offset);
177 offset += sizeof (void *);
88e17b57
BE
178 }
179}
180
181
182/* Iterates over the types in the structure that represents the class
183 encoding and sets the bits in mask according to each ivar type. */
184static void
185__objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
186{
187 struct objc_struct_layout layout;
188 unsigned int offset, align;
189 const char *ivar_type;
190
191 objc_layout_structure (type, &layout);
192
193 while (objc_layout_structure_next_member (&layout))
194 {
195 BOOL gc_invisible = NO;
196
197 objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
198
199 /* Skip the variable name */
200 if (*ivar_type == '"')
201 {
202 for (ivar_type++; *ivar_type++ != '"';)
203 /* do nothing */;
204 }
205
206 if (*ivar_type == _C_GCINVISIBLE)
207 {
208 gc_invisible = YES;
209 ivar_type++;
210 }
211
212 switch (*ivar_type) {
213 case _C_ID:
214 case _C_CLASS:
215 case _C_SEL:
216 case _C_PTR:
217 case _C_CHARPTR:
40165636
RB
218 if (! gc_invisible)
219 SET_BIT_FOR_OFFSET (mask, offset);
88e17b57
BE
220 break;
221
222 case _C_ARY_B:
223 __objc_gc_setup_array (mask, ivar_type, offset);
224 break;
225
226 case _C_STRUCT_B:
227 __objc_gc_setup_struct (mask, ivar_type, offset);
228 break;
229
230 case _C_UNION_B:
231 __objc_gc_setup_union (mask, ivar_type, offset);
232 break;
233
234 default:
235 break;
236 }
237 }
238}
239
240/* Computes in *type the full type encoding of this class including
241 its super classes. '*size' gives the total number of bytes allocated
242 into *type, '*current' the number of bytes used so far by the
243 encoding. */
244static void
245__objc_class_structure_encoding (Class class, char **type, int *size,
246 int *current)
247{
248 int i, ivar_count;
40165636 249 struct objc_ivar_list *ivars;
88e17b57 250
40165636 251 if (! class)
88e17b57
BE
252 {
253 strcat (*type, "{");
8c3e5222 254 (*current)++;
88e17b57
BE
255 return;
256 }
257
258 /* Add the type encodings of the super classes */
259 __objc_class_structure_encoding (class->super_class, type, size, current);
260
261 ivars = class->ivars;
40165636 262 if (! ivars)
88e17b57
BE
263 return;
264
265 ivar_count = ivars->ivar_count;
266
267 for (i = 0; i < ivar_count; i++)
268 {
269 struct objc_ivar *ivar = &(ivars->ivar_list[i]);
270 const char *ivar_type = ivar->ivar_type;
271 int len = strlen (ivar_type);
272
273 if (*current + len + 1 >= *size)
274 {
275 /* Increase the size of the encoding string so that it
276 contains this ivar's type. */
40165636 277 *size = ROUND (*current + len + 1, 10);
88e17b57
BE
278 *type = objc_realloc (*type, *size);
279 }
280 strcat (*type + *current, ivar_type);
281 *current += len;
282 }
283}
284
285
286/* Allocates the memory that will hold the type description for class
287 and calls the __objc_class_structure_encoding that generates this
288 value. */
289void
290__objc_generate_gc_type_description (Class class)
291{
292 GC_bitmap mask;
293 int bits_no, size;
294 int type_size = 10, current;
295 char *class_structure_type;
296
40165636 297 if (! CLS_ISCLASS (class))
88e17b57
BE
298 return;
299
300 /* We have to create a mask in which each bit counts for a pointer member.
301 We take into consideration all the non-pointer instance variables and we
302 round them up to the alignment. */
303
304 /* The number of bits in the mask is the size of an instance in bytes divided
305 by the size of a pointer. */
0b0b41a8 306 bits_no = (ROUND (class_getInstanceSize (class), sizeof (void *))
40165636
RB
307 / sizeof (void *));
308 size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
88e17b57
BE
309 mask = objc_atomic_malloc (size * sizeof (int));
310 memset (mask, 0, size * sizeof (int));
311
312 class_structure_type = objc_atomic_malloc (type_size);
313 *class_structure_type = current = 0;
314 __objc_class_structure_encoding (class, &class_structure_type,
315 &type_size, &current);
316 if (current + 1 == type_size)
317 class_structure_type = objc_realloc (class_structure_type, ++type_size);
318 strcat (class_structure_type + current, "}");
041dea56
OP
319#ifdef DEBUG
320 printf ("type description for '%s' is %s\n", class->name, class_structure_type);
321#endif
88e17b57
BE
322
323 __objc_gc_type_description_from_type (mask, class_structure_type);
324 objc_free (class_structure_type);
325
88e17b57
BE
326#ifdef DEBUG
327 printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
328 class_structure_type, class->name, bits_no, size);
329 {
330 int i;
331 for (i = 0; i < size; i++)
332 printf (" %lx", mask[i]);
333 }
334 puts ("");
335#endif
336
40165636 337 class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
88e17b57
BE
338}
339
340
341/* Returns YES if type denotes a pointer type, NO otherwise */
342static inline BOOL
343__objc_ivar_pointer (const char *type)
344{
345 type = objc_skip_type_qualifiers (type);
346
347 return (*type == _C_ID
348 || *type == _C_CLASS
349 || *type == _C_SEL
350 || *type == _C_PTR
351 || *type == _C_CHARPTR
352 || *type == _C_ATOM);
353}
354
355
356/* Mark the instance variable whose name is given by ivarname as a
357 weak pointer (a pointer hidden to the garbage collector) if
358 gc_invisible is true. If gc_invisible is false it unmarks the
359 instance variable and makes it a normal pointer, visible to the
360 garbage collector.
361
362 This operation only makes sense on instance variables that are
363 pointers. */
364void
40165636 365class_ivar_set_gcinvisible (Class class, const char *ivarname,
88e17b57
BE
366 BOOL gc_invisible)
367{
368 int i, ivar_count;
40165636 369 struct objc_ivar_list *ivars;
88e17b57 370
40165636 371 if (! class || ! ivarname)
88e17b57
BE
372 return;
373
374 ivars = class->ivars;
40165636 375 if (! ivars)
88e17b57
BE
376 return;
377
378 ivar_count = ivars->ivar_count;
379
380 for (i = 0; i < ivar_count; i++)
381 {
382 struct objc_ivar *ivar = &(ivars->ivar_list[i]);
383 const char *type;
384
40165636 385 if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
88e17b57
BE
386 continue;
387
388 assert (ivar->ivar_type);
389 type = ivar->ivar_type;
390
391 /* Skip the variable name */
392 if (*type == '"')
393 {
394 for (type++; *type++ != '"';)
395 /* do nothing */;
396 }
397
398 if (*type == _C_GCINVISIBLE)
399 {
400 char *new_type;
801a91f9 401 size_t len;
88e17b57 402
40165636 403 if (gc_invisible || ! __objc_ivar_pointer (type))
88e17b57
BE
404 return; /* The type of the variable already matches the
405 requested gc_invisible type */
406
801a91f9
DA
407 /* The variable is gc_invisible so we make it gc visible. */
408 new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
409 len = (type - ivar->ivar_type);
410 memcpy (new_type, ivar->ivar_type, len);
411 new_type[len] = 0;
88e17b57
BE
412 strcat (new_type, type + 1);
413 ivar->ivar_type = new_type;
414 }
415 else
416 {
417 char *new_type;
801a91f9 418 size_t len;
88e17b57 419
40165636 420 if (! gc_invisible || ! __objc_ivar_pointer (type))
88e17b57
BE
421 return; /* The type of the variable already matches the
422 requested gc_invisible type */
423
801a91f9
DA
424 /* The variable is gc visible so we make it gc_invisible. */
425 new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
55b21c7a
RFM
426
427 /* Copy the variable name. */
801a91f9
DA
428 len = (type - ivar->ivar_type);
429 memcpy (new_type, ivar->ivar_type, len);
55b21c7a
RFM
430 /* Add '!'. */
431 new_type[len++] = _C_GCINVISIBLE;
432 /* Copy the original types. */
433 strcpy (new_type + len, type);
434
88e17b57
BE
435 ivar->ivar_type = new_type;
436 }
437
438 __objc_generate_gc_type_description (class);
439 return;
440 }
441
442 /* Search the instance variable in the superclasses */
443 class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
444}
445
446#else /* !OBJC_WITH_GC */
447
448void
8f8c44cb 449__objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
88e17b57
BE
450{
451}
452
8f8c44cb 453void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
40165636 454 const char *ivarname __attribute__ ((__unused__)),
8f8c44cb 455 BOOL gc_invisible __attribute__ ((__unused__)))
88e17b57
BE
456{
457}
458
459#endif /* OBJC_WITH_GC */