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