xref: /dflybsd-src/contrib/gcc-4.7/libobjc/ivars.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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