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