1 /* GObject introspection: Compute structure offsets
3 * Copyright (C) 2008 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include "girffi-private.h"
24 /* The C standard specifies that an enumeration can be any char or any signed
25 * or unsigned integer type capable of resresenting all the values of the
26 * enumeration. We use test enumerations to figure out what choices the
31 ENUM_1 = 1 /* compiler could use int8, uint8, int16, uint16, int32, uint32 */
35 ENUM_2 = 128 /* compiler could use uint8, int16, uint16, int32, uint32 */
39 ENUM_3 = 257 /* compiler could use int16, uint16, int32, uint32 */
43 ENUM_4 = G_MAXSHORT + 1 /* compiler could use uint16, int32, uint32 */
47 ENUM_5 = G_MAXUSHORT + 1 /* compiler could use int32, uint32 */
51 ENUM_6 = ((guint)G_MAXINT) + 1 /* compiler could use uint32 */
54 /* GIrNodeValue has guint32 values, so if it matters to the ABI whether
55 * constant values are signed, we are in trouble. And we don't handle
56 * enums with > 32 bit values. */
60 ENUM_7 = -1 /* compiler could use int8, int16, int32 */
67 compute_enum_storage_type (GIrNodeEnum *enum_node)
70 guint32 max_value = 0;
73 if (enum_node->storage_type != GI_TYPE_TAG_VOID) /* already done */
76 for (l = enum_node->values; l; l = l->next)
78 GIrNodeValue *value = l->data;
79 if (value->value > max_value)
80 max_value = value->value;
84 width = sizeof (Enum1);
85 else if (max_value < 256)
86 width = sizeof (Enum2);
87 else if (max_value < G_MAXSHORT)
88 width = sizeof (Enum3);
89 else if (max_value < G_MAXUSHORT)
90 width = sizeof (Enum4);
91 else if (max_value < G_MAXINT)
92 width = sizeof (Enum5);
94 width = sizeof (Enum6);
97 enum_node->storage_type = GI_TYPE_TAG_UINT8;
99 enum_node->storage_type = GI_TYPE_TAG_UINT16;
101 enum_node->storage_type = GI_TYPE_TAG_UINT32;
103 enum_node->storage_type = GI_TYPE_TAG_UINT64;
105 g_error ("Unexpected enum width %d", width);
109 get_enum_size_alignment (GIrNodeEnum *enum_node,
115 compute_enum_storage_type (enum_node);
117 switch (enum_node->storage_type)
119 case GI_TYPE_TAG_INT8:
120 case GI_TYPE_TAG_UINT8:
121 type_ffi = &ffi_type_uint8;
123 case GI_TYPE_TAG_INT16:
124 case GI_TYPE_TAG_UINT16:
125 type_ffi = &ffi_type_uint16;
127 case GI_TYPE_TAG_INT32:
128 case GI_TYPE_TAG_UINT32:
129 type_ffi = &ffi_type_uint32;
131 case GI_TYPE_TAG_INT64:
132 case GI_TYPE_TAG_UINT64:
133 type_ffi = &ffi_type_uint64;
136 g_error ("Unexpected enum storage type %s",
137 g_type_tag_to_string (enum_node->storage_type));
140 *size = type_ffi->size;
141 *alignment = type_ffi->alignment;
147 get_interface_size_alignment (GIrNodeType *type,
155 GIrModule *iface_module;
157 if (!g_ir_find_node (module, modules, type->interface, &iface, &iface_module))
159 g_warning ("Can't resolve type '%s' for %s", type->interface, who);
165 g_ir_node_compute_offsets (iface, iface_module,
166 iface_module == module ? modules : NULL);
170 case G_IR_NODE_BOXED:
172 GIrNodeBoxed *boxed = (GIrNodeBoxed *)iface;
174 *alignment = boxed->alignment;
177 case G_IR_NODE_STRUCT:
179 GIrNodeStruct *struct_ = (GIrNodeStruct *)iface;
180 *size = struct_->size;
181 *alignment = struct_->alignment;
184 case G_IR_NODE_OBJECT:
185 case G_IR_NODE_INTERFACE:
187 GIrNodeInterface *interface = (GIrNodeInterface *)iface;
188 *size = interface->size;
189 *alignment = interface->alignment;
192 case G_IR_NODE_UNION:
194 GIrNodeUnion *union_ = (GIrNodeUnion *)iface;
195 *size = union_->size;
196 *alignment = union_->alignment;
200 case G_IR_NODE_FLAGS:
202 return get_enum_size_alignment ((GIrNodeEnum *)iface,
205 case G_IR_NODE_CALLBACK:
207 *size = ffi_type_pointer.size;
208 *alignment = ffi_type_pointer.alignment;
213 g_warning ("%s has is not a pointer and is of type %s",
215 g_ir_node_type_to_string (iface->type));
222 return *alignment > 0;
226 get_type_size_alignment (GIrNodeType *type,
235 if (type->tag == GI_TYPE_TAG_ARRAY)
237 gint elt_size, elt_alignment;
240 || !get_type_size_alignment(type->parameter_type1, module, modules,
241 &elt_size, &elt_alignment, who))
248 *size = type->size * elt_size;
249 *alignment = elt_alignment;
253 else if (type->is_pointer)
255 type_ffi = &ffi_type_pointer;
259 if (type->tag == GI_TYPE_TAG_INTERFACE)
261 return get_interface_size_alignment (type, module, modules, size, alignment, who);
265 type_ffi = g_ir_ffi_get_ffi_type (type->tag, type->is_pointer);
267 if (type_ffi == &ffi_type_void)
269 g_warning ("%s has void type", who);
274 else if (type_ffi == &ffi_type_pointer)
276 g_warning ("%s has is not a pointer and is of type %s",
278 g_type_tag_to_string (type->tag));
287 *size = type_ffi->size;
288 *alignment = type_ffi->alignment;
294 get_field_size_alignment (GIrNodeField *field,
295 GIrNode *parent_node,
304 who = g_strdup_printf ("field %s.%s.%s", module->name, parent_node->name, ((GIrNode *)field)->name);
308 *size = ffi_type_pointer.size;
309 *alignment = ffi_type_pointer.alignment;
313 success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
319 #define ALIGN(n, align) (((n) + (align) - 1) & ~((align) - 1))
322 compute_struct_field_offsets (GIrNode *node,
332 gboolean have_error = FALSE;
334 *alignment_out = -2; /* mark to detect recursion */
336 for (l = members; l; l = l->next)
338 GIrNode *member = (GIrNode *)l->data;
340 if (member->type == G_IR_NODE_FIELD)
342 GIrNodeField *field = (GIrNodeField *)member;
347 int member_alignment;
349 if (get_field_size_alignment (field, node,
351 &member_size, &member_alignment))
353 size = ALIGN (size, member_alignment);
354 alignment = MAX (alignment, member_alignment);
355 field->offset = size;
365 else if (member->type == G_IR_NODE_CALLBACK)
367 size = ALIGN (size, ffi_type_pointer.alignment);
368 alignment = MAX (alignment, ffi_type_pointer.alignment);
369 size += ffi_type_pointer.size;
373 /* Structs are tail-padded out to a multiple of their alignment */
374 size = ALIGN (size, alignment);
379 *alignment_out = alignment;
391 compute_union_field_offsets (GIrNode *node,
401 gboolean have_error = FALSE;
403 *alignment_out = -2; /* mark to detect recursion */
405 for (l = members; l; l = l->next)
407 GIrNode *member = (GIrNode *)l->data;
409 if (member->type == G_IR_NODE_FIELD)
411 GIrNodeField *field = (GIrNodeField *)member;
416 int member_alignment;
418 if (get_field_size_alignment (field, node,
420 &member_size, &member_alignment))
422 size = MAX (size, member_size);
423 alignment = MAX (alignment, member_alignment);
431 /* Unions are tail-padded out to a multiple of their alignment */
432 size = ALIGN (size, alignment);
437 *alignment_out = alignment;
449 check_needs_computation (GIrNode *node,
454 * 0: Not yet computed
455 * >0: Previously succeeded
456 * -1: Previously failed
461 g_warning ("Recursion encountered when computing the size of %s.%s",
462 module->name, node->name);
465 return alignment == 0;
469 * g_ir_node_compute_offsets:
471 * @module: Current module being processed
472 * @modules: all currently loaded modules
474 * If a node is a a structure or union, makes sure that the field
475 * offsets have been computed, and also computes the overall size and
476 * alignment for the type.
479 g_ir_node_compute_offsets (GIrNode *node,
485 case G_IR_NODE_BOXED:
487 GIrNodeBoxed *boxed = (GIrNodeBoxed *)node;
489 if (!check_needs_computation (node, module, boxed->alignment))
492 compute_struct_field_offsets (node, boxed->members,
494 &boxed->size, &boxed->alignment);
497 case G_IR_NODE_STRUCT:
499 GIrNodeStruct *struct_ = (GIrNodeStruct *)node;
501 if (!check_needs_computation (node, module, struct_->alignment))
504 compute_struct_field_offsets (node, struct_->members,
506 &struct_->size, &struct_->alignment);
509 case G_IR_NODE_OBJECT:
510 case G_IR_NODE_INTERFACE:
512 GIrNodeInterface *iface = (GIrNodeInterface *)node;
514 if (!check_needs_computation (node, module, iface->alignment))
517 compute_struct_field_offsets (node, iface->members,
519 &iface->size, &iface->alignment);
522 case G_IR_NODE_UNION:
524 GIrNodeUnion *union_ = (GIrNodeUnion *)node;
526 if (!check_needs_computation (node, module, union_->alignment))
529 compute_union_field_offsets (node, union_->members,
531 &union_->size, &union_->alignment);
535 case G_IR_NODE_FLAGS:
537 GIrNodeEnum *enum_ = (GIrNodeEnum *)node;
539 if (enum_->storage_type != GI_TYPE_TAG_VOID) /* already done */
542 compute_enum_storage_type (enum_);