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