ivars.c revision 1.7 1 1.1 mrg /* GNU Objective C Runtime ivar related functions.
2 1.7 mrg Copyright (C) 2010-2018 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.3 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