+ type_t *type = obstack_alloc(type_obst, sizeof(complex_type_t));
+ memset(type, 0, sizeof(complex_type_t));
+
+ type->kind = TYPE_COMPLEX;
+ type->base.qualifiers = qualifiers;
+ type->complex.akind = akind;
+
+ return identify_new_type(type);
+}
+
+/**
+ * Creates a new imaginary type.
+ *
+ * @param akind The kind of the atomic type.
+ * @param qualifiers Type qualifiers for the new type.
+ */
+type_t *make_imaginary_type(atomic_type_kind_t akind, type_qualifiers_t qualifiers)
+{
+ type_t *type = obstack_alloc(type_obst, sizeof(imaginary_type_t));
+ memset(type, 0, sizeof(imaginary_type_t));
+
+ type->kind = TYPE_IMAGINARY;
+ type->base.qualifiers = qualifiers;
+ type->imaginary.akind = akind;
+
+ return identify_new_type(type);
+}
+
+/**
+ * Creates a new pointer type.
+ *
+ * @param points_to The points-to type for the new type.
+ * @param qualifiers Type qualifiers for the new type.
+ */
+type_t *make_pointer_type(type_t *points_to, type_qualifiers_t qualifiers)
+{
+ type_t *type = obstack_alloc(type_obst, sizeof(pointer_type_t));
+ memset(type, 0, sizeof(pointer_type_t));
+
+ type->kind = TYPE_POINTER;
+ type->base.qualifiers = qualifiers;
+ type->pointer.points_to = points_to;
+ type->pointer.base_variable = NULL;
+
+ return identify_new_type(type);
+}
+
+/**
+ * Creates a new reference type.
+ *
+ * @param refers_to The referred-to type for the new type.
+ */
+type_t *make_reference_type(type_t *refers_to)
+{
+ type_t *type = obstack_alloc(type_obst, sizeof(reference_type_t));
+ memset(type, 0, sizeof(reference_type_t));
+
+ type->kind = TYPE_REFERENCE;
+ type->base.qualifiers = 0;
+ type->reference.refers_to = refers_to;
+
+ return identify_new_type(type);
+}
+
+/**
+ * Creates a new based pointer type.
+ *
+ * @param points_to The points-to type for the new type.
+ * @param qualifiers Type qualifiers for the new type.
+ * @param variable The based variable
+ */
+type_t *make_based_pointer_type(type_t *points_to,
+ type_qualifiers_t qualifiers, variable_t *variable)
+{
+ type_t *type = obstack_alloc(type_obst, sizeof(pointer_type_t));
+ memset(type, 0, sizeof(pointer_type_t));
+
+ type->kind = TYPE_POINTER;
+ type->base.qualifiers = qualifiers;
+ type->pointer.points_to = points_to;
+ type->pointer.base_variable = variable;
+
+ return identify_new_type(type);
+}
+
+
+type_t *make_array_type(type_t *element_type, size_t size,
+ type_qualifiers_t qualifiers)
+{
+ type_t *type = obstack_alloc(type_obst, sizeof(array_type_t));
+ memset(type, 0, sizeof(array_type_t));
+
+ type->kind = TYPE_ARRAY;
+ type->base.qualifiers = qualifiers;
+ type->array.element_type = element_type;
+ type->array.size = size;
+ type->array.size_constant = true;
+
+ return identify_new_type(type);
+}
+
+static entity_t *pack_bitfield_members(il_size_t *struct_offset,
+ il_alignment_t *struct_alignment,
+ bool packed, entity_t *first)
+{
+ il_size_t offset = *struct_offset;
+ il_alignment_t alignment = *struct_alignment;
+ size_t bit_offset = 0;
+
+ entity_t *member;
+ for (member = first; member != NULL; member = member->base.next) {
+ if (member->kind != ENTITY_COMPOUND_MEMBER)
+ break;
+
+ type_t *type = member->declaration.type;
+ if (type->kind != TYPE_BITFIELD)
+ break;
+
+ type_t *base_type = skip_typeref(type->bitfield.base_type);
+ il_alignment_t base_alignment = get_type_alignment(base_type);
+ il_alignment_t alignment_mask = base_alignment-1;
+ if (base_alignment > alignment)
+ alignment = base_alignment;
+
+ size_t bit_size = type->bitfield.bit_size;
+ if (!packed) {
+ bit_offset += (offset & alignment_mask) * BITS_PER_BYTE;
+ offset &= ~alignment_mask;
+ size_t base_size = get_type_size(base_type) * BITS_PER_BYTE;
+
+ if (bit_offset + bit_size > base_size || bit_size == 0) {
+ offset += (bit_offset+BITS_PER_BYTE-1) / BITS_PER_BYTE;
+ offset = (offset + base_alignment-1) & ~alignment_mask;
+ bit_offset = 0;
+ }
+ }
+
+ member->compound_member.offset = offset;
+ member->compound_member.bit_offset = bit_offset;
+
+ bit_offset += bit_size;
+ offset += bit_offset / BITS_PER_BYTE;
+ bit_offset %= BITS_PER_BYTE;
+ }
+
+ if (bit_offset > 0)
+ offset += 1;
+
+ *struct_offset = offset;
+ *struct_alignment = alignment;
+
+ return member;
+}
+
+/**
+ * Finish the construction of a struct type by calculating its size, offsets,
+ * alignment.
+ */
+void layout_struct_type(compound_type_t *type)
+{
+ assert(type->compound != NULL);
+
+ compound_t *compound = type->compound;
+ if (!compound->complete)
+ return;
+ if (type->compound->layouted)
+ return;
+
+ il_size_t offset = 0;
+ il_alignment_t alignment = compound->alignment;
+ bool need_pad = false;
+
+ entity_t *entry = compound->members.entities;
+ while (entry != NULL) {
+ if (entry->kind != ENTITY_COMPOUND_MEMBER) {
+ entry = entry->base.next;
+ continue;
+ }
+
+ type_t *m_type = entry->declaration.type;
+ type_t *skipped = skip_typeref(m_type);
+ if (! is_type_valid(skipped)) {
+ entry = entry->base.next;
+ continue;
+ }
+
+ if (skipped->kind == TYPE_BITFIELD) {
+ entry = pack_bitfield_members(&offset, &alignment,
+ compound->packed, entry);
+ continue;
+ }
+
+ il_alignment_t m_alignment = get_type_alignment(m_type);
+ if (m_alignment > alignment)
+ alignment = m_alignment;
+
+ if (!compound->packed) {
+ il_size_t new_offset = (offset + m_alignment-1) & -m_alignment;
+
+ if (new_offset > offset) {
+ need_pad = true;
+ offset = new_offset;
+ }
+ }
+
+ entry->compound_member.offset = offset;
+ offset += get_type_size(m_type);
+
+ entry = entry->base.next;
+ }
+
+ if (!compound->packed) {
+ il_size_t new_offset = (offset + alignment-1) & -alignment;
+ if (new_offset > offset) {
+ need_pad = true;
+ offset = new_offset;
+ }
+ }
+
+ if (need_pad) {
+ if (warning.padded) {
+ warningf(&compound->base.source_position, "'%T' needs padding",
+ type);
+ }
+ } else if (compound->packed && warning.packed) {
+ warningf(&compound->base.source_position,
+ "superfluous packed attribute on '%T'", type);
+ }
+
+ compound->size = offset;
+ compound->alignment = alignment;
+ compound->layouted = true;
+}
+
+/**
+ * Finish the construction of an union type by calculating
+ * its size and alignment.
+ */
+void layout_union_type(compound_type_t *type)
+{
+ assert(type->compound != NULL);
+
+ compound_t *compound = type->compound;
+ if (! compound->complete)
+ return;
+
+ il_size_t size = 0;
+ il_alignment_t alignment = compound->alignment;
+
+ entity_t *entry = compound->members.entities;
+ for (; entry != NULL; entry = entry->base.next) {
+ if (entry->kind != ENTITY_COMPOUND_MEMBER)
+ continue;
+
+ type_t *m_type = entry->declaration.type;
+ if (! is_type_valid(skip_typeref(m_type)))
+ continue;
+
+ entry->compound_member.offset = 0;
+ il_size_t m_size = get_type_size(m_type);
+ if (m_size > size)
+ size = m_size;
+ il_alignment_t m_alignment = get_type_alignment(m_type);
+ if (m_alignment > alignment)
+ alignment = m_alignment;
+ }
+ size = (size + alignment - 1) & -alignment;