annotate libobjc/ivars.c @ 158:494b0b89df80 default tip

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