[g-ir-compiler] Slightly less lame error messages
[gnome.gobject-introspection] / girepository / giroffsets.c
index f78e479..dcfd75e 100644 (file)
@@ -18,7 +18,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include "girffi.h"
+#include "girffi-private.h"
 #include "girnode.h"
 
 /* The C standard specifies that an enumeration can be any char or any signed
@@ -63,15 +63,15 @@ typedef enum {
 /* etc... */
 #endif
 
-static gboolean
-get_enum_size_alignment (GIrNodeEnum *enum_node,
-                        gint        *size,
-                        gint        *alignment)
+static void
+compute_enum_storage_type (GIrNodeEnum *enum_node)
 {
   GList *l;
   guint32 max_value = 0;
   int width;
-  ffi_type *type_ffi;
+
+  if (enum_node->storage_type != GI_TYPE_TAG_VOID) /* already done */
+    return;
 
   for (l = enum_node->values; l; l = l->next)
     {
@@ -94,15 +94,48 @@ get_enum_size_alignment (GIrNodeEnum *enum_node,
     width = sizeof (Enum6);
 
   if (width == 1)
-    type_ffi = &ffi_type_sint8;
+    enum_node->storage_type = GI_TYPE_TAG_UINT8;
   else if (width == 2)
-    type_ffi = &ffi_type_sint16;
+    enum_node->storage_type = GI_TYPE_TAG_UINT16;
   else if (width == 4)
-    type_ffi = &ffi_type_sint32;
+    enum_node->storage_type = GI_TYPE_TAG_UINT32;
   else if (width == 8)
-    type_ffi = &ffi_type_sint64;
+    enum_node->storage_type = GI_TYPE_TAG_UINT64;
   else
     g_error ("Unexpected enum width %d", width);
+}
+
+static gboolean
+get_enum_size_alignment (GIrNodeEnum *enum_node,
+                        gint        *size,
+                        gint        *alignment)
+{
+  ffi_type *type_ffi;
+
+  compute_enum_storage_type (enum_node);
+
+  switch (enum_node->storage_type)
+    {
+    case GI_TYPE_TAG_INT8:
+    case GI_TYPE_TAG_UINT8:
+      type_ffi = &ffi_type_uint8;
+      break;
+    case GI_TYPE_TAG_INT16:
+    case GI_TYPE_TAG_UINT16:
+      type_ffi = &ffi_type_uint16;
+      break;
+    case GI_TYPE_TAG_INT32:
+    case GI_TYPE_TAG_UINT32:
+      type_ffi = &ffi_type_uint32;
+      break;
+    case GI_TYPE_TAG_INT64:
+    case GI_TYPE_TAG_UINT64:
+      type_ffi = &ffi_type_uint64;
+      break;
+    default:
+      g_error ("Unexpected enum storage type %s",
+              g_type_tag_to_string (enum_node->storage_type));
+    }
 
   *size = type_ffi->size;
   *alignment = type_ffi->alignment;
@@ -112,17 +145,18 @@ get_enum_size_alignment (GIrNodeEnum *enum_node,
 
 static gboolean
 get_interface_size_alignment (GIrNodeType *type,
-                             GIrModule   *module,
+                              GIrModule   *module,
                              GList       *modules,
                              gint        *size,
-                             gint        *alignment)
+                             gint        *alignment,
+                              const char  *who)
 {
   GIrNode *iface;
   GIrModule *iface_module;
 
   if (!g_ir_find_node (module, modules, type->interface, &iface, &iface_module))
     {
-      g_warning ("Type for type name '%s' not found", type->interface);
+      g_ir_module_fatal (module, 0, "Can't resolve type '%s' for %s", type->interface, who);
       *size = -1;
       *alignment = -1;
       return FALSE;
@@ -147,6 +181,14 @@ get_interface_size_alignment (GIrNodeType *type,
        *alignment = struct_->alignment;
        break;
       }
+    case G_IR_NODE_OBJECT:
+    case G_IR_NODE_INTERFACE:
+      {
+       GIrNodeInterface *interface = (GIrNodeInterface *)iface;
+       *size = interface->size;
+       *alignment = interface->alignment;
+       break;
+      }
     case G_IR_NODE_UNION:
       {
        GIrNodeUnion *union_ = (GIrNodeUnion *)iface;
@@ -168,7 +210,8 @@ get_interface_size_alignment (GIrNodeType *type,
       }
     default:
       {
-       g_warning ("Unexpected non-pointer field of type %s in structure",
+       g_warning ("%s has is not a pointer and is of type %s",
+                   who,
                   g_ir_node_type_to_string (iface->type));
        *size = -1;
        *alignment = -1;
@@ -180,16 +223,34 @@ get_interface_size_alignment (GIrNodeType *type,
 }
 
 static gboolean
-get_field_size_alignment (GIrNodeField *field,
-                         GIrModule    *module,
-                         GList        *modules,
-                         gint         *size,
-                         gint         *alignment)
+get_type_size_alignment (GIrNodeType *type,
+                         GIrModule   *module,
+                         GList       *modules,
+                         gint        *size,
+                         gint        *alignment,
+                         const char  *who)
 {
-  GIrNodeType *type = field->type;
   ffi_type *type_ffi;
 
-  if (type->is_pointer)
+  if (type->tag == GI_TYPE_TAG_ARRAY)
+    {
+      gint elt_size, elt_alignment;
+          
+      if (!type->has_size
+          || !get_type_size_alignment(type->parameter_type1, module, modules,
+                                      &elt_size, &elt_alignment, who))
+        {
+          *size = -1;
+          *alignment = -1;
+          return FALSE;
+        }
+          
+      *size = type->size * elt_size;
+      *alignment = elt_alignment;
+          
+      return TRUE;
+    }
+  else if (type->is_pointer)
     {
       type_ffi = &ffi_type_pointer;
     }
@@ -197,25 +258,23 @@ get_field_size_alignment (GIrNodeField *field,
     {
       if (type->tag == GI_TYPE_TAG_INTERFACE)
        {
-         return get_interface_size_alignment (type,
-                                              module, modules,
-                                              size, alignment);
+         return get_interface_size_alignment (type, module, modules, size, alignment, who);
        }
       else
        {
-         type_ffi = g_ir_ffi_get_ffi_type (type->tag);
+         type_ffi = g_ir_ffi_get_ffi_type (type->tag, type->is_pointer);
 
          if (type_ffi == &ffi_type_void)
            {
-             g_warning ("field '%s' has void type", ((GIrNode *)field)->name);
+             g_warning ("%s has void type", who);
              *size = -1;
              *alignment = -1;
              return FALSE;
            }
          else if (type_ffi == &ffi_type_pointer)
            {
-             g_warning ("non-pointer field '%s' has unhandled type %s",
-                        ((GIrNode *)field)->name,
+             g_warning ("%s has is not a pointer and is of type %s",
+                         who,
                         g_type_tag_to_string (type->tag));
              *size = -1;
              *alignment = -1;
@@ -231,10 +290,37 @@ get_field_size_alignment (GIrNodeField *field,
   return TRUE;
 }
 
+static gboolean
+get_field_size_alignment (GIrNodeField *field,
+                         GIrNode      *parent_node,
+                         GIrModule    *module,
+                         GList        *modules,
+                         gint         *size,
+                         gint         *alignment)
+{
+  gchar *who;
+  gboolean success;
+  
+  who = g_strdup_printf ("field %s.%s.%s", module->name, parent_node->name, ((GIrNode *)field)->name);
+
+  if (field->callback)
+    {
+      *size = ffi_type_pointer.size;
+      *alignment = ffi_type_pointer.alignment;
+      success = TRUE;
+    }
+  else
+    success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
+  g_free (who);
+
+  return success;
+}
+
 #define ALIGN(n, align) (((n) + (align) - 1) & ~((align) - 1))
 
 static gboolean
-compute_struct_field_offsets (GList       *members,
+compute_struct_field_offsets (GIrNode     *node,
+                             GList       *members,
                              GIrModule   *module,
                              GList       *modules,
                              gint        *size_out,
@@ -260,7 +346,7 @@ compute_struct_field_offsets (GList       *members,
              int member_size;
              int member_alignment;
 
-             if (get_field_size_alignment (field,
+             if (get_field_size_alignment (field, node,
                                            module, modules,
                                            &member_size, &member_alignment))
                {
@@ -278,8 +364,9 @@ compute_struct_field_offsets (GList       *members,
        }
       else if (member->type == G_IR_NODE_CALLBACK)
        {
-         size = ffi_type_pointer.size;
-         alignment = ffi_type_pointer.alignment;
+          size = ALIGN (size, ffi_type_pointer.alignment);
+          alignment = MAX (alignment, ffi_type_pointer.alignment);
+         size += ffi_type_pointer.size;
        }
     }
 
@@ -301,7 +388,8 @@ compute_struct_field_offsets (GList       *members,
 }
 
 static gboolean
-compute_union_field_offsets (GList       *members,
+compute_union_field_offsets (GIrNode     *node,
+                            GList       *members,
                             GIrModule   *module,
                             GList       *modules,
                             gint        *size_out,
@@ -327,7 +415,7 @@ compute_union_field_offsets (GList       *members,
              int member_size;
              int member_alignment;
 
-             if (get_field_size_alignment (field,
+             if (get_field_size_alignment (field, node,
                                            module, modules,
                                            &member_size, &member_alignment))
                {
@@ -381,7 +469,7 @@ check_needs_computation (GIrNode   *node,
  * g_ir_node_compute_offsets:
  * @node: a #GIrNode
  * @module: Current module being processed
- * @moudles: all currently loaded modules
+ * @modules: all currently loaded modules
  *
  * If a node is a a structure or union, makes sure that the field
  * offsets have been computed, and also computes the overall size and
@@ -401,7 +489,7 @@ g_ir_node_compute_offsets (GIrNode   *node,
        if (!check_needs_computation (node, module, boxed->alignment))
          return;
 
-       compute_struct_field_offsets (boxed->members,
+       compute_struct_field_offsets (node, boxed->members,
                                      module, modules,
                                      &boxed->size, &boxed->alignment);
        break;
@@ -413,11 +501,24 @@ g_ir_node_compute_offsets (GIrNode   *node,
        if (!check_needs_computation (node, module, struct_->alignment))
          return;
 
-       compute_struct_field_offsets (struct_->members,
+       compute_struct_field_offsets (node, struct_->members,
                                      module, modules,
                                      &struct_->size, &struct_->alignment);
        break;
       }
+    case G_IR_NODE_OBJECT:
+    case G_IR_NODE_INTERFACE:
+      {
+       GIrNodeInterface *iface = (GIrNodeInterface *)node;
+
+       if (!check_needs_computation (node, module, iface->alignment))
+         return;
+
+       compute_struct_field_offsets (node, iface->members,
+                                     module, modules,
+                                     &iface->size, &iface->alignment);
+       break;
+      }
     case G_IR_NODE_UNION:
       {
        GIrNodeUnion *union_ = (GIrNodeUnion *)node;
@@ -425,11 +526,23 @@ g_ir_node_compute_offsets (GIrNode   *node,
        if (!check_needs_computation (node, module, union_->alignment))
          return;
 
-       compute_union_field_offsets (union_->members,
+       compute_union_field_offsets (node, union_->members,
                                     module, modules,
                                     &union_->size, &union_->alignment);
        break;
       }
+    case G_IR_NODE_ENUM:
+    case G_IR_NODE_FLAGS:
+      {
+       GIrNodeEnum *enum_ = (GIrNodeEnum *)node;
+
+       if (enum_->storage_type != GI_TYPE_TAG_VOID) /* already done */
+         return;
+
+       compute_enum_storage_type (enum_);
+
+       break;
+      }
     default:
       /* Nothing to do */
       return;