123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- /* Basic data types for Objective C.
- Copyright (C) 1998-2015 Free Software Foundation, Inc.
- Contributed by Ovidiu Predescu.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- #include "objc-private/common.h"
- #include "objc/objc.h"
- #if OBJC_WITH_GC
- #include "tconfig.h"
- #include <assert.h>
- #include <ctype.h> /* For isdigit. */
- #include <string.h>
- #include <stdlib.h>
- #include "objc/runtime.h"
- #include "objc-private/module-abi-8.h"
- #include <gc.h>
- #include <limits.h>
- /* gc_typed.h uses the following but doesn't declare them */
- typedef GC_word word;
- typedef GC_signed_word signed_word;
- #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
- #include <gc_typed.h>
- /* The following functions set up in `mask` the corresponding pointers.
- The offset is incremented with the size of the type. */
- #define ROUND(V, A) \
- ({ typeof (V) __v = (V); typeof (A) __a = (A); \
- __a * ((__v+__a - 1)/__a); })
- #define SET_BIT_FOR_OFFSET(mask, offset) \
- GC_set_bit (mask, offset / sizeof (void *))
- /* Some prototypes */
- static void
- __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
- static void
- __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
- static void
- __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
- {
- int i, len = atoi (type + 1);
- while (isdigit (*++type))
- /* do nothing */; /* skip the size of the array */
- switch (*type) {
- case _C_ARY_B:
- for (i = 0; i < len; i++)
- __objc_gc_setup_array (mask, type, offset);
- break;
- case _C_STRUCT_B:
- for (i = 0; i < len; i++)
- __objc_gc_setup_struct (mask, type, offset);
- break;
- case _C_UNION_B:
- for (i = 0; i < len; i++)
- __objc_gc_setup_union (mask, type, offset);
- break;
- default:
- break;
- }
- }
- static void
- __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
- {
- struct objc_struct_layout layout;
- unsigned int position;
- const char *mtype;
- objc_layout_structure (type, &layout);
- while (objc_layout_structure_next_member (&layout))
- {
- BOOL gc_invisible = NO;
- objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
- /* Skip the variable name */
- if (*mtype == '"')
- {
- for (mtype++; *mtype++ != '"';)
- /* do nothing */;
- }
- if (*mtype == _C_GCINVISIBLE)
- {
- gc_invisible = YES;
- mtype++;
- }
- /* Add to position the offset of this structure */
- position += offset;
- switch (*mtype) {
- case _C_ID:
- case _C_CLASS:
- case _C_SEL:
- case _C_PTR:
- case _C_CHARPTR:
- case _C_ATOM:
- if (! gc_invisible)
- SET_BIT_FOR_OFFSET (mask, position);
- break;
- case _C_ARY_B:
- __objc_gc_setup_array (mask, mtype, position);
- break;
- case _C_STRUCT_B:
- __objc_gc_setup_struct (mask, mtype, position);
- break;
- case _C_UNION_B:
- __objc_gc_setup_union (mask, mtype, position);
- break;
- default:
- break;
- }
- }
- }
- static void
- __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
- {
- /* Sub-optimal, quick implementation: assume the union is made of
- pointers, set up the mask accordingly. */
- int i, size, align;
- /* Skip the variable name */
- if (*type == '"')
- {
- for (type++; *type++ != '"';)
- /* do nothing */;
- }
- size = objc_sizeof_type (type);
- align = objc_alignof_type (type);
- offset = ROUND (offset, align);
- for (i = 0; i < size; i += sizeof (void *))
- {
- SET_BIT_FOR_OFFSET (mask, offset);
- offset += sizeof (void *);
- }
- }
- /* Iterates over the types in the structure that represents the class
- encoding and sets the bits in mask according to each ivar type. */
- static void
- __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
- {
- struct objc_struct_layout layout;
- unsigned int offset, align;
- const char *ivar_type;
- objc_layout_structure (type, &layout);
- while (objc_layout_structure_next_member (&layout))
- {
- BOOL gc_invisible = NO;
- objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
- /* Skip the variable name */
- if (*ivar_type == '"')
- {
- for (ivar_type++; *ivar_type++ != '"';)
- /* do nothing */;
- }
- if (*ivar_type == _C_GCINVISIBLE)
- {
- gc_invisible = YES;
- ivar_type++;
- }
- switch (*ivar_type) {
- case _C_ID:
- case _C_CLASS:
- case _C_SEL:
- case _C_PTR:
- case _C_CHARPTR:
- if (! gc_invisible)
- SET_BIT_FOR_OFFSET (mask, offset);
- break;
- case _C_ARY_B:
- __objc_gc_setup_array (mask, ivar_type, offset);
- break;
- case _C_STRUCT_B:
- __objc_gc_setup_struct (mask, ivar_type, offset);
- break;
- case _C_UNION_B:
- __objc_gc_setup_union (mask, ivar_type, offset);
- break;
- default:
- break;
- }
- }
- }
- /* Computes in *type the full type encoding of this class including
- its super classes. '*size' gives the total number of bytes allocated
- into *type, '*current' the number of bytes used so far by the
- encoding. */
- static void
- __objc_class_structure_encoding (Class class, char **type, int *size,
- int *current)
- {
- int i, ivar_count;
- struct objc_ivar_list *ivars;
- if (! class)
- {
- strcat (*type, "{");
- (*current)++;
- return;
- }
- /* Add the type encodings of the super classes */
- __objc_class_structure_encoding (class->super_class, type, size, current);
- ivars = class->ivars;
- if (! ivars)
- return;
- ivar_count = ivars->ivar_count;
- for (i = 0; i < ivar_count; i++)
- {
- struct objc_ivar *ivar = &(ivars->ivar_list[i]);
- const char *ivar_type = ivar->ivar_type;
- int len = strlen (ivar_type);
- if (*current + len + 1 >= *size)
- {
- /* Increase the size of the encoding string so that it
- contains this ivar's type. */
- *size = ROUND (*current + len + 1, 10);
- *type = objc_realloc (*type, *size);
- }
- strcat (*type + *current, ivar_type);
- *current += len;
- }
- }
- /* Allocates the memory that will hold the type description for class
- and calls the __objc_class_structure_encoding that generates this
- value. */
- void
- __objc_generate_gc_type_description (Class class)
- {
- GC_bitmap mask;
- int bits_no, size;
- int type_size = 10, current;
- char *class_structure_type;
- if (! CLS_ISCLASS (class))
- return;
- /* We have to create a mask in which each bit counts for a pointer member.
- We take into consideration all the non-pointer instance variables and we
- round them up to the alignment. */
- /* The number of bits in the mask is the size of an instance in bytes divided
- by the size of a pointer. */
- bits_no = (ROUND (class_getInstanceSize (class), sizeof (void *))
- / sizeof (void *));
- size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
- mask = objc_atomic_malloc (size * sizeof (int));
- memset (mask, 0, size * sizeof (int));
- class_structure_type = objc_atomic_malloc (type_size);
- *class_structure_type = current = 0;
- __objc_class_structure_encoding (class, &class_structure_type,
- &type_size, ¤t);
- if (current + 1 == type_size)
- class_structure_type = objc_realloc (class_structure_type, ++type_size);
- strcat (class_structure_type + current, "}");
- #ifdef DEBUG
- printf ("type description for '%s' is %s\n", class->name, class_structure_type);
- #endif
-
- __objc_gc_type_description_from_type (mask, class_structure_type);
- objc_free (class_structure_type);
- #ifdef DEBUG
- printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
- class_structure_type, class->name, bits_no, size);
- {
- int i;
- for (i = 0; i < size; i++)
- printf (" %lx", mask[i]);
- }
- puts ("");
- #endif
- class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
- }
- /* Returns YES if type denotes a pointer type, NO otherwise */
- static inline BOOL
- __objc_ivar_pointer (const char *type)
- {
- type = objc_skip_type_qualifiers (type);
- return (*type == _C_ID
- || *type == _C_CLASS
- || *type == _C_SEL
- || *type == _C_PTR
- || *type == _C_CHARPTR
- || *type == _C_ATOM);
- }
- /* Mark the instance variable whose name is given by ivarname as a
- weak pointer (a pointer hidden to the garbage collector) if
- gc_invisible is true. If gc_invisible is false it unmarks the
- instance variable and makes it a normal pointer, visible to the
- garbage collector.
- This operation only makes sense on instance variables that are
- pointers. */
- void
- class_ivar_set_gcinvisible (Class class, const char *ivarname,
- BOOL gc_invisible)
- {
- int i, ivar_count;
- struct objc_ivar_list *ivars;
- if (! class || ! ivarname)
- return;
- ivars = class->ivars;
- if (! ivars)
- return;
- ivar_count = ivars->ivar_count;
- for (i = 0; i < ivar_count; i++)
- {
- struct objc_ivar *ivar = &(ivars->ivar_list[i]);
- const char *type;
- if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
- continue;
- assert (ivar->ivar_type);
- type = ivar->ivar_type;
- /* Skip the variable name */
- if (*type == '"')
- {
- for (type++; *type++ != '"';)
- /* do nothing */;
- }
- if (*type == _C_GCINVISIBLE)
- {
- char *new_type;
- size_t len;
- if (gc_invisible || ! __objc_ivar_pointer (type))
- return; /* The type of the variable already matches the
- requested gc_invisible type */
- /* The variable is gc_invisible so we make it gc visible. */
- new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
- len = (type - ivar->ivar_type);
- memcpy (new_type, ivar->ivar_type, len);
- new_type[len] = 0;
- strcat (new_type, type + 1);
- ivar->ivar_type = new_type;
- }
- else
- {
- char *new_type;
- size_t len;
- if (! gc_invisible || ! __objc_ivar_pointer (type))
- return; /* The type of the variable already matches the
- requested gc_invisible type */
- /* The variable is gc visible so we make it gc_invisible. */
- new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
- /* Copy the variable name. */
- len = (type - ivar->ivar_type);
- memcpy (new_type, ivar->ivar_type, len);
- /* Add '!'. */
- new_type[len++] = _C_GCINVISIBLE;
- /* Copy the original types. */
- strcpy (new_type + len, type);
- ivar->ivar_type = new_type;
- }
- __objc_generate_gc_type_description (class);
- return;
- }
- /* Search the instance variable in the superclasses */
- class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
- }
- #else /* !OBJC_WITH_GC */
- void
- __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
- {
- }
- void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
- const char *ivarname __attribute__ ((__unused__)),
- BOOL gc_invisible __attribute__ ((__unused__)))
- {
- }
- #endif /* OBJC_WITH_GC */
|