Ejemplo n.º 1
0
unsigned get_ctype_size(type_t const *const type)
{
	switch (type->kind) {
	case TYPE_ERROR:
		return 0;
	case TYPE_ATOMIC:
	case TYPE_IMAGINARY:
	case TYPE_ENUM:
		return get_atomic_type_size(type->atomic.akind);
	case TYPE_COMPLEX:
		return get_atomic_type_size(type->atomic.akind) * 2;
	case TYPE_COMPOUND_STRUCT:
	case TYPE_COMPOUND_UNION:
		return type->compound.compound->size;
	case TYPE_FUNCTION:
	case TYPE_VOID:
		return 1; /* GCC extension. */
	case TYPE_REFERENCE:
	case TYPE_POINTER:
		return pointer_properties.size;
	case TYPE_ARRAY: {
		/* TODO: correct if element_type is aligned? */
		unsigned element_size = get_ctype_size(type->array.element_type);
		return type->array.size * element_size;
	}
	case TYPE_TYPEDEF:
		return get_ctype_size(type->typedeft.typedefe->type);
	case TYPE_TYPEOF:
		return get_ctype_size(type->typeoft.typeof_type);
	case TYPE_BUILTIN_TEMPLATE:
		break;
	}
	panic("invalid type");
}
Ejemplo n.º 2
0
static SExp make_cfunc(void* cfunc, SExp rettype, SExp argtypes) {
	int argnum = length(argtypes);
	CFunction* p = (CFunction*)smalloc(sizeof(*p) + sizeof(*p->args) * (argnum-1), TRUE);
	SExp q;
	int argsize = 0;
	int i;
	p->typeinfo = &TCFunc;
	p->cfunc = cfunc;
	p->rettype = sym2ctype(rettype);
	p->argnum = argnum;
	for (q = argtypes, i = 0; consp(q); q = CDR(q), ++i) {
		eCType t = sym2ctype(CAR(q));
		int size = get_ctype_size(t);
		p->args[i].type = t;
		p->args[i].size = size;
		argsize += size;
	}
	p->argsize = argsize;
	return ptr2s(p);
}
Ejemplo n.º 3
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;
}