Ejemplo n.º 1
0
static unsigned get_object_alignment(expression_t const *const expr)
{
	entity_t *ent;
	switch (expr->kind) {
	case EXPR_ARRAY_ACCESS:      return get_address_alignment(expr->array_access.array_ref);
	case EXPR_UNARY_DEREFERENCE: return get_address_alignment(expr->unary.value);
	case EXPR_REFERENCE:         ent = expr->reference.entity;      break;
	case EXPR_SELECT:            ent = expr->select.compound_entry; break;
	default:                     return get_type_alignment(expr->base.type);
	}
	assert(is_declaration(ent));
	return get_declaration_alignment(&ent->declaration);
}
Ejemplo n.º 2
0
void layout_compound(compound_t *const compound)
{
	bool     const is_union   = compound->base.kind == ENTITY_UNION;
	unsigned       alignment  = compound->alignment;
	size_t         bit_offset = 0;
	unsigned       size       = 0;
	bool           need_pad   = false;
	for (entity_t *entry = compound->members.first_entity; entry;
	     entry = entry->base.next) {
		if (entry->kind != ENTITY_COMPOUND_MEMBER)
			continue;

		compound_member_t *const member = &entry->compound_member;
		type_t            *const m_type = skip_typeref(member->base.type);
		if (!is_type_valid(m_type))
			continue;

		unsigned m_alignment = get_declaration_alignment(&member->base);
		alignment = MAX(alignment, m_alignment);

		unsigned const m_size = get_ctype_size(m_type);
		if (is_union) {
			size = MAX(size, m_size);
		} else if (member->bitfield) {
			unsigned const alignment_mask = m_alignment - 1;
			size_t   const base_size      = m_size * BITS_PER_BYTE;
			size_t   const bit_size       = member->bit_size;

			bit_offset += (size & alignment_mask) * BITS_PER_BYTE;
			size       &= ~alignment_mask;
			if (bit_offset + bit_size > base_size
				|| (bit_size == 0 && !(member->base.modifiers & DM_PACKED))) {
				size      += (bit_offset + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
				size       = round_up2(size, m_alignment);
				bit_offset = 0;
			}

			if (target.byte_order_big_endian) {
				member->offset     = size & ~alignment_mask;
				member->bit_offset = base_size - bit_offset - bit_size;
			} else {
				member->offset     = size;
				member->bit_offset = bit_offset;
			}

			bit_offset += bit_size;
			size       += bit_offset / BITS_PER_BYTE;
			bit_offset %= BITS_PER_BYTE;
		} else {
			if (bit_offset != 0) {
				bit_offset = 0;
				size      += 1;
			}

			unsigned const new_size = round_up2(size, m_alignment);
			if (new_size > size) {
				need_pad = true;
				size     = new_size;
			}

			member->offset = size;
			size          += m_size;
		}
	}

	if (bit_offset != 0)
		size += 1;

	unsigned const new_size = round_up2(size, alignment);
	if (new_size > size) {
		need_pad = true;
		size     = new_size;
	}

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

	compound->size      = size;
	compound->alignment = alignment;
}