* 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
/* 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)
{
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;
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;
*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;
}
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;
}
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;
}
{
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;
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,
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))
{
}
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;
}
}
}
static gboolean
-compute_union_field_offsets (GList *members,
+compute_union_field_offsets (GIrNode *node,
+ GList *members,
GIrModule *module,
GList *modules,
gint *size_out,
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))
{
* 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
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;
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;
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;