diff mbox

libobjc: fix class_addIvar()'s alignment

Message ID 2F993563-D8BD-44F9-8A2D-D9B037E59707@meta-innovation.com
State New
Headers show

Commit Message

Nicola Pero Dec. 24, 2010, 6:41 p.m. UTC
This patch changes class_addIvar() to be compatible with the Apple  
runtime and
understand the alignment argument in the same way as the Apple runtime
understands it: as the log2 of the alignment, as opposed to the actual  
alignment.

Committed to trunk.

Thanks

-                        __alignof__ (unsigned long), @encode  
(unsigned long)))
+                        log_2_of (__alignof__ (unsigned long)),  
@encode (unsigned long)))
        abort ();

      objc_registerClassPair (new_class);
@@ -135,7 +153,7 @@
        abort ();

      if (! class_addIvar (new_class, "variable_ivar", sizeof (id),
-                        __alignof__ (id), @encode (id)))
+                        log_2_of (__alignof__ (id)), @encode (id)))
        abort ();

      if (! class_addMethod (new_class, @selector (setVariable:),  
method_getImplementation (method1),
diff mbox

Patch

Index: ChangeLog
===================================================================
--- ChangeLog   (revision 168229)
+++ ChangeLog   (working copy)
@@ -1,5 +1,12 @@ 
  2010-12-24  Nicola Pero  <nicola.pero@meta-innovation.com>

+       * objc/runtime.h (class_addIvar): Updated documentation.  The
+       alignment is actually the log_2 of the alignment in bytes.
+       * ivars.c (class_addIvar): Corresponding change to the
+       implementation.
+
+2010-12-24  Nicola Pero  <nicola.pero@meta-innovation.com>
+
         * objc/runtime.h (sel_getType): Renamed to  
sel_getTypeEncoding to
         be consistent with method_getTypeEncoding and
         ivar_getTypeEncoding.
Index: ivars.c
===================================================================
--- ivars.c     (revision 168228)
+++ ivars.c     (working copy)
@@ -212,7 +212,7 @@ 

  BOOL
  class_addIvar (Class class_, const char * ivar_name, size_t size,
-              unsigned char alignment, const char *type)
+              unsigned char log_2_of_alignment, const char *type)
  {
    struct objc_ivar_list *ivars;

@@ -270,6 +270,7 @@ 
       size. */
    {
      struct objc_ivar *ivar = &(ivars->ivar_list[ivars->ivar_count -  
1]);
+    unsigned int alignment = 1 << log_2_of_alignment;
      int misalignment;

      ivar->ivar_name = objc_malloc (strlen (ivar_name) + 1);
Index: objc/runtime.h
===================================================================
--- objc/runtime.h      (revision 168229)
+++ objc/runtime.h      (working copy)
@@ -352,14 +352,16 @@ 
     using objc_allocateClassPair() and has not been registered with the
     runtime using objc_registerClassPair() yet.  You can not add
     instance variables to classes already registered with the runtime.
-   'size' is the size of the instance variable, 'alignment' the
-   alignment, and 'type' the type encoding of the variable type.  You
-   can use sizeof(), __alignof__() and @encode() to determine the
-   right 'size', 'alignment' and 'type' for your instance variable.
-   For example, to add an instance variable name "my_variable" and of
-   type 'id', you can use:
+   'size' is the size of the instance variable, 'log_2_of_alignment'
+   the alignment as a power of 2 (so 0 means alignment to a 1 byte
+   boundary, 1 means alignment to a 2 byte boundary, 2 means alignment
+   to a 4 byte boundary, etc), and 'type' the type encoding of the
+   variable type.  You can use sizeof(), log2(__alignof__()) and
+   @encode() to determine the right 'size', 'alignment' and 'type' for
+   your instance variable.  For example, to add an instance variable
+   name "my_variable" and of type 'id', you can use:

-   class_addIvar (class, "my_variable", sizeof (id), __alignof__ (id),
+   class_addIvar (class, "my_variable", sizeof (id), log2  
( __alignof__ (id)),
                    @encode (id));

     Return YES if the variable was added, and NO if not.  In
@@ -368,7 +370,7 @@ 
     'type' is NULL, or 'size' is 0.
   */
  objc_EXPORT BOOL class_addIvar (Class class_, const char *  
ivar_name, size_t size,
-                               unsigned char alignment, const char  
*type);
+                               unsigned char log_2_of_alignment,  
const char *type);

  /* Return the name of the property.  Return NULL if 'property' is
     NULL.  */

Index: ChangeLog
===================================================================
--- ChangeLog   (revision 168229)
+++ ChangeLog   (working copy)
@@ -1,5 +1,11 @@ 
  2010-12-24  Nicola Pero  <nicola.pero@meta-innovation.com>

+       * objc.dg/gnu-api-2-class.m: Updated test to pass log_2 of the
+       alignment to class_addIvar, instead of the alignment itself.
+       * obj-c++.dg/gnu-api-2-class.mm: Same change.
+
+2010-12-24  Nicola Pero  <nicola.pero@meta-innovation.com>
+
         * objc.dg/gnu-api-2-sel.m: Updated for renaming of  
sel_getType to
         sel_getTypeEncoding.  Test that sel_getTypeEncoding returns  
NULL
         when called with a NULL argument.  Added test for
Index: objc.dg/gnu-api-2-class.m
===================================================================
--- objc.dg/gnu-api-2-class.m   (revision 168229)
+++ objc.dg/gnu-api-2-class.m   (working copy)
@@ -62,6 +62,24 @@ 
  - (id) mySelf;
  @end

+/* Hack to calculate the log2 of a byte alignment.  */
+unsigned char
+log_2_of (unsigned int x)
+{
+  unsigned char result = 0;
+
+  /* We count how many times we need to divide by 2 before we reach 1.
+     This algorithm is good enough for the small numbers (such as 8,
+     16 or 64) that we have to deal with.  */
+  while (x > 1)
+    {
+      x = x / 2;
+      result++;
+    }
+
+  return result;
+}
+
  int main(int argc, void **args)
  {
    /* Functions are tested in alphabetical order.  */
@@ -74,15 +92,15 @@ 
        abort ();

      if (! class_addIvar (new_class, "variable2_ivar", sizeof (id),
-                        __alignof__ (id), @encode (id)))
+                        log_2_of (__alignof__ (id)), @encode (id)))
        abort ();

      if (! class_addIvar (new_class, "variable3_ivar", sizeof  
(unsigned char),
-                        __alignof__ (unsigned char), @encode  
(unsigned char)))
+                        log_2_of (__alignof__ (unsigned char)),  
@encode (unsigned char)))
        abort ();

      if (! class_addIvar (new_class, "variable4_ivar", sizeof  
(unsigned long),
-                        __alignof__ (unsigned long), @encode  
(unsigned long)))
+                        log_2_of (__alignof__ (unsigned long)),  
@encode (unsigned long)))
        abort ();

      objc_registerClassPair (new_class);
@@ -135,7 +153,7 @@ 
        abort ();

      if (! class_addIvar (new_class, "variable_ivar", sizeof (id),
-                        __alignof__ (id), @encode (id)))
+                        log_2_of (__alignof__ (id)), @encode (id)))
        abort ();

      if (! class_addMethod (new_class, @selector (setVariable:),  
method_getImplementation (method1),
Index: obj-c++.dg/gnu-api-2-class.mm
===================================================================
--- obj-c++.dg/gnu-api-2-class.mm       (revision 168228)
+++ obj-c++.dg/gnu-api-2-class.mm       (working copy)
@@ -62,6 +62,24 @@ 
  - (id) mySelf;
  @end

+/* Hack to calculate the log2 of a byte alignment.  */
+unsigned char
+log_2_of (unsigned int x)
+{
+  unsigned char result = 0;
+
+  /* We count how many times we need to divide by 2 before we reach 1.
+     This algorithm is good enough for the small numbers (such as 8,
+     16 or 64) that we have to deal with.  */
+  while (x > 1)
+    {
+      x = x / 2;
+      result++;
+    }
+
+  return result;
+}
+
  int main ()
  {
    /* Functions are tested in alphabetical order.  */
@@ -74,15 +92,15 @@ 
        abort ();

      if (! class_addIvar (new_class, "variable2_ivar", sizeof (id),
-                        __alignof__ (id), @encode (id)))
+                        log_2_of (__alignof__ (id)), @encode (id)))
        abort ();

      if (! class_addIvar (new_class, "variable3_ivar", sizeof  
(unsigned char),
-                        __alignof__ (unsigned char), @encode  
(unsigned char)))
+                        log_2_of (__alignof__ (unsigned char)),  
@encode (unsigned char)))
        abort ();

      if (! class_addIvar (new_class, "variable4_ivar", sizeof  
(unsigned long),