1 1.1 mrg /* GNU Objective C Runtime ivar related functions. 2 1.1.1.11 mrg Copyright (C) 2010-2024 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Nicola Pero 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify it under the 8 1.1 mrg terms of the GNU General Public License as published by the Free Software 9 1.1 mrg Foundation; either version 3, or (at your option) any later version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 1.1 mrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 1.1 mrg details. 15 1.1 mrg 16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg You should have received a copy of the GNU General Public License and 21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg <http://www.gnu.org/licenses/>. */ 24 1.1 mrg 25 1.1 mrg #include "objc-private/common.h" 26 1.1 mrg #include "objc/runtime.h" 27 1.1 mrg #include "objc-private/module-abi-8.h" /* For runtime structures */ 28 1.1 mrg #include "objc/thr.h" 29 1.1 mrg #include "objc-private/runtime.h" /* the kitchen sink */ 30 1.1 mrg #include <string.h> /* For strcmp. */ 31 1.1 mrg #include <stdlib.h> /* For malloc. */ 32 1.1 mrg 33 1.1 mrg struct objc_ivar * 34 1.1 mrg class_getInstanceVariable (Class class_, const char *name) 35 1.1 mrg { 36 1.1 mrg if (class_ != Nil && name != NULL && ! CLS_IS_IN_CONSTRUCTION (class_)) 37 1.1 mrg { 38 1.1 mrg while (class_ != Nil) 39 1.1 mrg { 40 1.1 mrg struct objc_ivar_list *ivars = class_->ivars; 41 1.1 mrg if (ivars != NULL) 42 1.1 mrg { 43 1.1 mrg int i; 44 1.1 mrg 45 1.1 mrg for (i = 0; i < ivars->ivar_count; i++) 46 1.1 mrg { 47 1.1 mrg struct objc_ivar *ivar = &(ivars->ivar_list[i]); 48 1.1 mrg 49 1.1 mrg if (!strcmp (ivar->ivar_name, name)) 50 1.1 mrg return ivar; 51 1.1 mrg } 52 1.1 mrg } 53 1.1 mrg class_ = class_getSuperclass (class_); 54 1.1 mrg } 55 1.1 mrg } 56 1.1 mrg return NULL; 57 1.1 mrg } 58 1.1 mrg 59 1.1 mrg struct objc_ivar * 60 1.1 mrg class_getClassVariable (Class class_, const char *name) 61 1.1 mrg { 62 1.1 mrg if (class_ == Nil) 63 1.1 mrg return NULL; 64 1.1 mrg 65 1.1 mrg /* Logically, since a class is an instance of its meta-class, and 66 1.1 mrg since its class methods are the instance methods of the 67 1.1 mrg meta-class, class variables should be instance variables of the 68 1.1 mrg meta-class. That is different from the normal use of having 69 1.1 mrg 'static' variables in the class implementation file, because 70 1.1 mrg every class would have its own variables. 71 1.1 mrg 72 1.1 mrg Anyway, it is all speculative at this stage, but if we get class 73 1.1 mrg variables in Objective-C, it is conceivable that this 74 1.1 mrg implementation should work. */ 75 1.1 mrg return class_getInstanceVariable (class_->class_pointer, name); 76 1.1 mrg } 77 1.1 mrg 78 1.1 mrg void * 79 1.1 mrg object_getIndexedIvars (id object) 80 1.1 mrg { 81 1.1 mrg if (object == nil) 82 1.1 mrg return NULL; 83 1.1 mrg else 84 1.1 mrg return (void *)(((char *)object) 85 1.1 mrg + object->class_pointer->instance_size); 86 1.1 mrg } 87 1.1 mrg 88 1.1 mrg struct objc_ivar * 89 1.1 mrg object_getInstanceVariable (id object, const char *name, void **returnValue) 90 1.1 mrg { 91 1.1 mrg if (object == nil || name == NULL) 92 1.1 mrg return NULL; 93 1.1 mrg else 94 1.1 mrg { 95 1.1 mrg struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name); 96 1.1 mrg 97 1.1 mrg if (variable != NULL && returnValue != NULL) 98 1.1 mrg { 99 1.1 mrg char *location = (char *)object + variable->ivar_offset; 100 1.1 mrg 101 1.1 mrg *returnValue = *((id *)location); 102 1.1 mrg } 103 1.1 mrg 104 1.1 mrg return variable; 105 1.1 mrg } 106 1.1 mrg } 107 1.1 mrg 108 1.1 mrg struct objc_ivar * 109 1.1 mrg object_setInstanceVariable (id object, const char *name, void *newValue) 110 1.1 mrg { 111 1.1 mrg if (object == nil || name == NULL) 112 1.1 mrg return NULL; 113 1.1 mrg else 114 1.1 mrg { 115 1.1 mrg struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name); 116 1.1 mrg 117 1.1 mrg if (variable != NULL) 118 1.1 mrg { 119 1.1 mrg char *location = (char *)object + variable->ivar_offset; 120 1.1 mrg 121 1.1 mrg *((id *)location) = (id)newValue; 122 1.1 mrg } 123 1.1 mrg 124 1.1 mrg return variable; 125 1.1 mrg } 126 1.1 mrg } 127 1.1 mrg 128 1.1 mrg id object_getIvar (id object, struct objc_ivar * variable) 129 1.1 mrg { 130 1.1 mrg if (object == nil || variable == NULL) 131 1.1 mrg return nil; 132 1.1 mrg else 133 1.1 mrg { 134 1.1 mrg char *location = (char *)object + variable->ivar_offset; 135 1.1 mrg 136 1.1 mrg return *((id *)location); 137 1.1 mrg } 138 1.1 mrg } 139 1.1 mrg 140 1.1 mrg void object_setIvar (id object, struct objc_ivar * variable, id value) 141 1.1 mrg { 142 1.1 mrg if (object == nil || variable == NULL) 143 1.1 mrg return; 144 1.1 mrg else 145 1.1 mrg { 146 1.1 mrg char *location = (char *)object + variable->ivar_offset; 147 1.1 mrg 148 1.1 mrg *((id *)location) = value; 149 1.1 mrg } 150 1.1 mrg } 151 1.1 mrg 152 1.1 mrg const char * ivar_getName (struct objc_ivar * variable) 153 1.1 mrg { 154 1.1 mrg if (variable == NULL) 155 1.1 mrg return NULL; 156 1.1 mrg 157 1.1 mrg return variable->ivar_name; 158 1.1 mrg } 159 1.1 mrg 160 1.1 mrg ptrdiff_t ivar_getOffset (struct objc_ivar * variable) 161 1.1 mrg { 162 1.1 mrg if (variable == NULL) 163 1.1 mrg return 0; 164 1.1 mrg 165 1.1 mrg return (ptrdiff_t)(variable->ivar_offset); 166 1.1 mrg } 167 1.1 mrg 168 1.1 mrg const char * ivar_getTypeEncoding (struct objc_ivar * variable) 169 1.1 mrg { 170 1.1 mrg if (variable == NULL) 171 1.1 mrg return NULL; 172 1.1 mrg 173 1.1 mrg return variable->ivar_type; 174 1.1 mrg } 175 1.1 mrg 176 1.1 mrg struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars) 177 1.1 mrg { 178 1.1 mrg unsigned int count = 0; 179 1.1 mrg struct objc_ivar **returnValue = NULL; 180 1.1 mrg struct objc_ivar_list* ivar_list; 181 1.1 mrg 182 1.1.1.2 mrg if (class_ == Nil || CLS_IS_IN_CONSTRUCTION (class_) || !class_->ivars) 183 1.1 mrg { 184 1.1 mrg if (numberOfReturnedIvars) 185 1.1 mrg *numberOfReturnedIvars = 0; 186 1.1 mrg return NULL; 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg /* Count how many ivars we have. */ 190 1.1 mrg ivar_list = class_->ivars; 191 1.1 mrg count = ivar_list->ivar_count; 192 1.1 mrg 193 1.1 mrg if (count != 0) 194 1.1 mrg { 195 1.1 mrg unsigned int i = 0; 196 1.1 mrg 197 1.1 mrg /* Allocate enough memory to hold them. */ 198 1.1 mrg returnValue = (struct objc_ivar **)(malloc (sizeof (struct objc_ivar *) * (count + 1))); 199 1.1 mrg 200 1.1 mrg /* Copy the ivars. */ 201 1.1 mrg for (i = 0; i < count; i++) 202 1.1 mrg returnValue[i] = &(ivar_list->ivar_list[i]); 203 1.1 mrg 204 1.1 mrg returnValue[i] = NULL; 205 1.1 mrg } 206 1.1 mrg 207 1.1 mrg if (numberOfReturnedIvars) 208 1.1 mrg *numberOfReturnedIvars = count; 209 1.1 mrg 210 1.1 mrg return returnValue; 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg BOOL 214 1.1 mrg class_addIvar (Class class_, const char * ivar_name, size_t size, 215 1.1 mrg unsigned char log_2_of_alignment, const char *type) 216 1.1 mrg { 217 1.1 mrg struct objc_ivar_list *ivars; 218 1.1 mrg 219 1.1 mrg if (class_ == Nil 220 1.1 mrg || (! CLS_IS_IN_CONSTRUCTION (class_)) 221 1.1 mrg || ivar_name == NULL 222 1.1 mrg || (strcmp (ivar_name, "") == 0) 223 1.1 mrg || size == 0 224 1.1 mrg || type == NULL) 225 1.1 mrg return NO; 226 1.1 mrg 227 1.1 mrg /* Check if the class has an instance variable with that name 228 1.1 mrg already. */ 229 1.1 mrg ivars = class_->ivars; 230 1.1 mrg 231 1.1 mrg if (ivars != NULL) 232 1.1 mrg { 233 1.1 mrg int i; 234 1.1 mrg 235 1.1 mrg for (i = 0; i < ivars->ivar_count; i++) 236 1.1 mrg { 237 1.1 mrg struct objc_ivar *ivar = &(ivars->ivar_list[i]); 238 1.1 mrg 239 1.1 mrg if (strcmp (ivar->ivar_name, ivar_name) == 0) 240 1.1 mrg return NO; 241 1.1 mrg } 242 1.1 mrg } 243 1.1 mrg 244 1.1 mrg /* Ok, no direct ivars. Check superclasses. */ 245 1.1 mrg if (class_getInstanceVariable (objc_getClass ((char *)(class_->super_class)), 246 1.1 mrg ivar_name)) 247 1.1 mrg return NO; 248 1.1 mrg 249 1.1 mrg /* Good. Create space for the new instance variable. */ 250 1.1 mrg if (ivars) 251 1.1 mrg { 252 1.1 mrg int ivar_count = ivars->ivar_count + 1; 253 1.1 mrg int new_size = sizeof (struct objc_ivar_list) 254 1.1 mrg + (ivar_count - 1) * sizeof (struct objc_ivar); 255 1.1 mrg 256 1.1 mrg ivars = (struct objc_ivar_list*) objc_realloc (ivars, new_size); 257 1.1 mrg ivars->ivar_count = ivar_count; 258 1.1 mrg class_->ivars = ivars; 259 1.1 mrg } 260 1.1 mrg else 261 1.1 mrg { 262 1.1 mrg int new_size = sizeof (struct objc_ivar_list); 263 1.1 mrg 264 1.1 mrg ivars = (struct objc_ivar_list*) objc_malloc (new_size); 265 1.1 mrg ivars->ivar_count = 1; 266 1.1 mrg class_->ivars = ivars; 267 1.1 mrg } 268 1.1 mrg 269 1.1 mrg /* Now ivars is set to a list of instance variables of the right 270 1.1 mrg size. */ 271 1.1 mrg { 272 1.1 mrg struct objc_ivar *ivar = &(ivars->ivar_list[ivars->ivar_count - 1]); 273 1.1 mrg unsigned int alignment = 1 << log_2_of_alignment; 274 1.1 mrg int misalignment; 275 1.1 mrg 276 1.1 mrg ivar->ivar_name = objc_malloc (strlen (ivar_name) + 1); 277 1.1 mrg strcpy ((char *)ivar->ivar_name, ivar_name); 278 1.1 mrg 279 1.1 mrg ivar->ivar_type = objc_malloc (strlen (type) + 1); 280 1.1 mrg strcpy ((char *)ivar->ivar_type, type); 281 1.1 mrg 282 1.1 mrg /* The new instance variable is placed at the end of the existing 283 1.1 mrg instance_size, at the first byte that is aligned with 284 1.1 mrg alignment. */ 285 1.1 mrg misalignment = class_->instance_size % alignment; 286 1.1 mrg 287 1.1 mrg if (misalignment == 0) 288 1.1 mrg ivar->ivar_offset = class_->instance_size; 289 1.1 mrg else 290 1.1 mrg ivar->ivar_offset = class_->instance_size - misalignment + alignment; 291 1.1 mrg 292 1.1 mrg class_->instance_size = ivar->ivar_offset + size; 293 1.1 mrg } 294 1.1 mrg 295 1.1 mrg return YES; 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg 299 1.1 mrg const char * 300 1.1 mrg property_getName (struct objc_property * property __attribute__ ((__unused__))) 301 1.1 mrg { 302 1.1 mrg if (property == NULL) 303 1.1 mrg return NULL; 304 1.1 mrg 305 1.1 mrg /* TODO: New ABI. */ 306 1.1 mrg /* The current ABI does not have any information on properties. */ 307 1.1 mrg return NULL; 308 1.1 mrg } 309 1.1 mrg 310 1.1 mrg const char * 311 1.1 mrg property_getAttributes (struct objc_property * property __attribute__ ((__unused__))) 312 1.1 mrg { 313 1.1 mrg if (property == NULL) 314 1.1 mrg return NULL; 315 1.1 mrg 316 1.1 mrg /* TODO: New ABI. */ 317 1.1 mrg /* The current ABI does not have any information on properties. */ 318 1.1 mrg return NULL; 319 1.1 mrg } 320 1.1 mrg 321 1.1 mrg struct objc_property * 322 1.1 mrg class_getProperty (Class class_ __attribute__ ((__unused__)), 323 1.1 mrg const char *propertyName __attribute__ ((__unused__))) 324 1.1 mrg { 325 1.1 mrg if (class_ == NULL || propertyName == NULL) 326 1.1 mrg return NULL; 327 1.1 mrg 328 1.1 mrg /* TODO: New ABI. */ 329 1.1 mrg /* The current ABI does not have any information on class properties. */ 330 1.1 mrg return NULL; 331 1.1 mrg } 332 1.1 mrg 333 1.1 mrg struct objc_property ** 334 1.1 mrg class_copyPropertyList (Class class_ __attribute__ ((__unused__)), 335 1.1 mrg unsigned int *numberOfReturnedProperties __attribute__ ((__unused__))) 336 1.1 mrg { 337 1.1 mrg if (class_ == Nil) 338 1.1 mrg { 339 1.1 mrg if (numberOfReturnedProperties) 340 1.1 mrg *numberOfReturnedProperties = 0; 341 1.1 mrg return NULL; 342 1.1 mrg } 343 1.1 mrg 344 1.1 mrg /* TODO: New ABI. */ 345 1.1 mrg /* The current ABI does not have any information on class properties. */ 346 1.1 mrg if (numberOfReturnedProperties) 347 1.1 mrg *numberOfReturnedProperties = 0; 348 1.1 mrg 349 1.1 mrg return NULL; 350 1.1 mrg } 351 1.1 mrg 352 1.1 mrg const char * 353 1.1 mrg class_getIvarLayout (Class class_ __attribute__ ((__unused__))) 354 1.1 mrg { 355 1.1 mrg return NULL; 356 1.1 mrg } 357 1.1 mrg 358 1.1 mrg const char * 359 1.1 mrg class_getWeakIvarLayout (Class class_ __attribute__ ((__unused__))) 360 1.1 mrg { 361 1.1 mrg return NULL; 362 1.1 mrg } 363 1.1 mrg 364 1.1 mrg void 365 1.1 mrg class_setIvarLayout (Class class_ __attribute__ ((__unused__)), 366 1.1 mrg const char *layout __attribute__ ((__unused__))) 367 1.1 mrg { 368 1.1 mrg return; 369 1.1 mrg } 370 1.1 mrg 371 1.1 mrg void 372 1.1 mrg class_setWeakIvarLayout (Class class_ __attribute__ ((__unused__)), 373 1.1 mrg const char *layout __attribute__ ((__unused__))) 374 1.1 mrg { 375 1.1 mrg return; 376 1.1 mrg } 377