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