Пример #1
0
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 = skip_typeref(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_compound(m_type);
		if (m_alignment > alignment)
			alignment = m_alignment;
	}
	size = (size + alignment - 1) & -alignment;

	compound->size      = size;
	compound->alignment = alignment;
}
Пример #2
0
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)
			continue;
		if (!member->compound_member.bitfield)
			break;

		type_t *const base_type = skip_typeref(member->declaration.type);
		il_alignment_t base_alignment = get_type_alignment_compound(base_type);
		il_alignment_t alignment_mask = base_alignment-1;
		if (base_alignment > alignment)
			alignment = base_alignment;

		size_t bit_size = member->compound_member.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;
			}
		}

		if (byte_order_big_endian) {
			size_t base_size = get_type_size(base_type) * BITS_PER_BYTE;
			member->compound_member.offset     = offset & ~alignment_mask;
			member->compound_member.bit_offset = base_size - bit_offset - bit_size;
		} else {
			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;
}
Пример #3
0
unsigned get_type_alignment_compound(type_t const *const type)
{
	switch (type->kind) {
	case TYPE_ATOMIC:
	case TYPE_COMPLEX:
	case TYPE_IMAGINARY:
	case TYPE_ENUM:
		return atomic_type_properties[type->atomic.akind].struct_alignment;

	case TYPE_TYPEDEF: {
		il_alignment_t const alignment = get_type_alignment_compound(type->typedeft.typedefe->type);
		return MAX(type->typedeft.typedefe->alignment, alignment);
	}

	case TYPE_TYPEOF:
		return get_type_alignment_compound(type->typeoft.typeof_type);

	default:
		return get_type_alignment(type);
	}
}
Пример #4
0
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 *const m_type  = skip_typeref(entry->declaration.type);
		if (!is_type_valid(m_type)) {
			entry = entry->base.next;
			continue;
		}

		if (entry->compound_member.bitfield) {
			entry = pack_bitfield_members(&offset, &alignment,
			                              compound->packed, entry);
			continue;
		}

		il_alignment_t m_alignment = get_type_alignment_compound(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;
		}
	}

	source_position_t const *const pos = &compound->base.source_position;
	if (need_pad) {
		warningf(WARN_PADDED, pos, "'%T' needs padding", type);
	} else if (compound->packed) {
		warningf(WARN_PACKED, pos, "superfluous packed attribute on '%T'", type);
	}

	compound->size      = offset;
	compound->alignment = alignment;
	compound->layouted  = true;
}