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