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