1 /* Basic data types for Objective C.
2 Copyright (C) 1998, 2002, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
3 Contributed by Ovidiu Predescu.
5 This file is part of GCC.
7 GCC 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 3, or (at your option)
12 GCC 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.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "objc-private/common.h"
28 #include "objc/objc.h"
29 #include "objc/encoding.h"
40 /* gc_typed.h uses the following but doesn't declare them */
42 typedef GC_signed_word signed_word
;
43 #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
47 /* The following functions set up in `mask` the corresponding pointers.
48 The offset is incremented with the size of the type. */
51 ({ typeof (V) __v = (V); typeof (A) __a = (A); \
52 __a * ((__v+__a - 1)/__a); })
54 #define SET_BIT_FOR_OFFSET(mask, offset) \
55 GC_set_bit (mask, offset / sizeof (void *))
59 __objc_gc_setup_struct (GC_bitmap mask
, const char *type
, int offset
);
61 __objc_gc_setup_union (GC_bitmap mask
, const char *type
, int offset
);
65 __objc_gc_setup_array (GC_bitmap mask
, const char *type
, int offset
)
67 int i
, len
= atoi (type
+ 1);
69 while (isdigit (*++type
))
70 /* do nothing */; /* skip the size of the array */
74 for (i
= 0; i
< len
; i
++)
75 __objc_gc_setup_array (mask
, type
, offset
);
79 for (i
= 0; i
< len
; i
++)
80 __objc_gc_setup_struct (mask
, type
, offset
);
84 for (i
= 0; i
< len
; i
++)
85 __objc_gc_setup_union (mask
, type
, offset
);
94 __objc_gc_setup_struct (GC_bitmap mask
, const char *type
, int offset
)
96 struct objc_struct_layout layout
;
97 unsigned int position
;
100 objc_layout_structure (type
, &layout
);
102 while (objc_layout_structure_next_member (&layout
))
104 BOOL gc_invisible
= NO
;
106 objc_layout_structure_get_info (&layout
, &position
, NULL
, &mtype
);
108 /* Skip the variable name */
111 for (mtype
++; *mtype
++ != '"';)
115 if (*mtype
== _C_GCINVISIBLE
)
121 /* Add to position the offset of this structure */
132 SET_BIT_FOR_OFFSET (mask
, position
);
136 __objc_gc_setup_array (mask
, mtype
, position
);
140 __objc_gc_setup_struct (mask
, mtype
, position
);
144 __objc_gc_setup_union (mask
, mtype
, position
);
154 __objc_gc_setup_union (GC_bitmap mask
, const char *type
, int offset
)
156 /* Sub-optimal, quick implementation: assume the union is made of
157 pointers, set up the mask accordingly. */
161 /* Skip the variable name */
164 for (type
++; *type
++ != '"';)
168 size
= objc_sizeof_type (type
);
169 align
= objc_alignof_type (type
);
171 offset
= ROUND (offset
, align
);
172 for (i
= 0; i
< size
; i
+= sizeof (void *))
174 SET_BIT_FOR_OFFSET (mask
, offset
);
175 offset
+= sizeof (void *);
180 /* Iterates over the types in the structure that represents the class
181 encoding and sets the bits in mask according to each ivar type. */
183 __objc_gc_type_description_from_type (GC_bitmap mask
, const char *type
)
185 struct objc_struct_layout layout
;
186 unsigned int offset
, align
;
187 const char *ivar_type
;
189 objc_layout_structure (type
, &layout
);
191 while (objc_layout_structure_next_member (&layout
))
193 BOOL gc_invisible
= NO
;
195 objc_layout_structure_get_info (&layout
, &offset
, &align
, &ivar_type
);
197 /* Skip the variable name */
198 if (*ivar_type
== '"')
200 for (ivar_type
++; *ivar_type
++ != '"';)
204 if (*ivar_type
== _C_GCINVISIBLE
)
210 switch (*ivar_type
) {
217 SET_BIT_FOR_OFFSET (mask
, offset
);
221 __objc_gc_setup_array (mask
, ivar_type
, offset
);
225 __objc_gc_setup_struct (mask
, ivar_type
, offset
);
229 __objc_gc_setup_union (mask
, ivar_type
, offset
);
238 /* Computes in *type the full type encoding of this class including
239 its super classes. '*size' gives the total number of bytes allocated
240 into *type, '*current' the number of bytes used so far by the
243 __objc_class_structure_encoding (Class
class, char **type
, int *size
,
247 struct objc_ivar_list
*ivars
;
256 /* Add the type encodings of the super classes */
257 __objc_class_structure_encoding (class->super_class
, type
, size
, current
);
259 ivars
= class->ivars
;
263 ivar_count
= ivars
->ivar_count
;
265 for (i
= 0; i
< ivar_count
; i
++)
267 struct objc_ivar
*ivar
= &(ivars
->ivar_list
[i
]);
268 const char *ivar_type
= ivar
->ivar_type
;
269 int len
= strlen (ivar_type
);
271 if (*current
+ len
+ 1 >= *size
)
273 /* Increase the size of the encoding string so that it
274 contains this ivar's type. */
275 *size
= ROUND (*current
+ len
+ 1, 10);
276 *type
= objc_realloc (*type
, *size
);
278 strcat (*type
+ *current
, ivar_type
);
284 /* Allocates the memory that will hold the type description for class
285 and calls the __objc_class_structure_encoding that generates this
288 __objc_generate_gc_type_description (Class
class)
292 int type_size
= 10, current
;
293 char *class_structure_type
;
295 if (! CLS_ISCLASS (class))
298 /* We have to create a mask in which each bit counts for a pointer member.
299 We take into consideration all the non-pointer instance variables and we
300 round them up to the alignment. */
302 /* The number of bits in the mask is the size of an instance in bytes divided
303 by the size of a pointer. */
304 bits_no
= (ROUND (class_get_instance_size (class), sizeof (void *))
306 size
= ROUND (bits_no
, BITS_PER_WORD
) / BITS_PER_WORD
;
307 mask
= objc_atomic_malloc (size
* sizeof (int));
308 memset (mask
, 0, size
* sizeof (int));
310 class_structure_type
= objc_atomic_malloc (type_size
);
311 *class_structure_type
= current
= 0;
312 __objc_class_structure_encoding (class, &class_structure_type
,
313 &type_size
, ¤t
);
314 if (current
+ 1 == type_size
)
315 class_structure_type
= objc_realloc (class_structure_type
, ++type_size
);
316 strcat (class_structure_type
+ current
, "}");
318 printf ("type description for '%s' is %s\n", class->name
, class_structure_type
);
321 __objc_gc_type_description_from_type (mask
, class_structure_type
);
322 objc_free (class_structure_type
);
325 printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
326 class_structure_type
, class->name
, bits_no
, size
);
329 for (i
= 0; i
< size
; i
++)
330 printf (" %lx", mask
[i
]);
335 class->gc_object_type
= (void *) GC_make_descriptor (mask
, bits_no
);
339 /* Returns YES if type denotes a pointer type, NO otherwise */
341 __objc_ivar_pointer (const char *type
)
343 type
= objc_skip_type_qualifiers (type
);
345 return (*type
== _C_ID
349 || *type
== _C_CHARPTR
350 || *type
== _C_ATOM
);
354 /* Mark the instance variable whose name is given by ivarname as a
355 weak pointer (a pointer hidden to the garbage collector) if
356 gc_invisible is true. If gc_invisible is false it unmarks the
357 instance variable and makes it a normal pointer, visible to the
360 This operation only makes sense on instance variables that are
363 class_ivar_set_gcinvisible (Class
class, const char *ivarname
,
367 struct objc_ivar_list
*ivars
;
369 if (! class || ! ivarname
)
372 ivars
= class->ivars
;
376 ivar_count
= ivars
->ivar_count
;
378 for (i
= 0; i
< ivar_count
; i
++)
380 struct objc_ivar
*ivar
= &(ivars
->ivar_list
[i
]);
383 if (! ivar
->ivar_name
|| strcmp (ivar
->ivar_name
, ivarname
))
386 assert (ivar
->ivar_type
);
387 type
= ivar
->ivar_type
;
389 /* Skip the variable name */
392 for (type
++; *type
++ != '"';)
396 if (*type
== _C_GCINVISIBLE
)
401 if (gc_invisible
|| ! __objc_ivar_pointer (type
))
402 return; /* The type of the variable already matches the
403 requested gc_invisible type */
405 /* The variable is gc_invisible so we make it gc visible. */
406 new_type
= objc_atomic_malloc (strlen(ivar
->ivar_type
));
407 len
= (type
- ivar
->ivar_type
);
408 memcpy (new_type
, ivar
->ivar_type
, len
);
410 strcat (new_type
, type
+ 1);
411 ivar
->ivar_type
= new_type
;
418 if (! gc_invisible
|| ! __objc_ivar_pointer (type
))
419 return; /* The type of the variable already matches the
420 requested gc_invisible type */
422 /* The variable is gc visible so we make it gc_invisible. */
423 new_type
= objc_malloc (strlen(ivar
->ivar_type
) + 2);
424 len
= (type
- ivar
->ivar_type
);
425 memcpy (new_type
, ivar
->ivar_type
, len
);
427 strcat (new_type
, "!");
428 strcat (new_type
, type
);
429 ivar
->ivar_type
= new_type
;
432 __objc_generate_gc_type_description (class);
436 /* Search the instance variable in the superclasses */
437 class_ivar_set_gcinvisible (class->super_class
, ivarname
, gc_invisible
);
440 #else /* !OBJC_WITH_GC */
443 __objc_generate_gc_type_description (Class
class __attribute__ ((__unused__
)))
447 void class_ivar_set_gcinvisible (Class
class __attribute__ ((__unused__
)),
448 const char *ivarname
__attribute__ ((__unused__
)),
449 BOOL gc_invisible
__attribute__ ((__unused__
)))
453 #endif /* OBJC_WITH_GC */