unsigned flags; /**< type flags from atomic_type_flag_t */
};
+/**
+ * Returns the size of a type node.
+ *
+ * @param kind the type kind
+ */
+static size_t get_type_struct_size(type_kind_t kind)
+{
+ static const size_t sizes[] = {
+ [TYPE_ATOMIC] = sizeof(atomic_type_t),
+ [TYPE_COMPLEX] = sizeof(complex_type_t),
+ [TYPE_IMAGINARY] = sizeof(imaginary_type_t),
+ [TYPE_BITFIELD] = sizeof(bitfield_type_t),
+ [TYPE_COMPOUND_STRUCT] = sizeof(compound_type_t),
+ [TYPE_COMPOUND_UNION] = sizeof(compound_type_t),
+ [TYPE_ENUM] = sizeof(enum_type_t),
+ [TYPE_FUNCTION] = sizeof(function_type_t),
+ [TYPE_POINTER] = sizeof(pointer_type_t),
+ [TYPE_ARRAY] = sizeof(array_type_t),
+ [TYPE_BUILTIN] = sizeof(builtin_type_t),
+ [TYPE_TYPEDEF] = sizeof(typedef_type_t),
+ [TYPE_TYPEOF] = sizeof(typeof_type_t),
+ };
+ assert(lengthof(sizes) == (int)TYPE_TYPEOF + 1);
+ assert(kind <= TYPE_TYPEOF);
+ assert(sizes[kind] != 0);
+ return sizes[kind];
+}
+
+type_t *allocate_type_zero(type_kind_t kind)
+{
+ size_t size = get_type_struct_size(kind);
+ type_t *res = obstack_alloc(type_obst, size);
+ memset(res, 0, size);
+ res->base.kind = kind;
+
+ return res;
+}
+
/**
* Properties of atomic types.
*/
props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 4;
props[ATOMIC_TYPE_LONGLONG].alignment = 4;
props[ATOMIC_TYPE_ULONGLONG].alignment = 4;
- if (firm_opt.os_support == OS_SUPPORT_MACHO) {
- props[ATOMIC_TYPE_LONG_DOUBLE].size = 16;
- props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 16;
+ if (force_long_double_size > 0) {
+ props[ATOMIC_TYPE_LONG_DOUBLE].size = force_long_double_size;
+ props[ATOMIC_TYPE_LONG_DOUBLE].alignment = force_long_double_size;
}
/* TODO: make this configurable for platforms which do not use byte sized
}
}
-/**
- * Return the size of a type AST node.
- *
- * @param type The type.
- */
-static size_t get_type_struct_size(const type_t *type)
-{
- switch(type->kind) {
- case TYPE_ATOMIC: return sizeof(atomic_type_t);
- case TYPE_COMPLEX: return sizeof(complex_type_t);
- case TYPE_IMAGINARY: return sizeof(imaginary_type_t);
- case TYPE_COMPOUND_STRUCT:
- case TYPE_COMPOUND_UNION: return sizeof(compound_type_t);
- case TYPE_ENUM: return sizeof(enum_type_t);
- case TYPE_FUNCTION: return sizeof(function_type_t);
- case TYPE_POINTER: return sizeof(pointer_type_t);
- case TYPE_REFERENCE: return sizeof(reference_type_t);
- case TYPE_ARRAY: return sizeof(array_type_t);
- case TYPE_BUILTIN: return sizeof(builtin_type_t);
- case TYPE_TYPEDEF: return sizeof(typedef_type_t);
- case TYPE_TYPEOF: return sizeof(typeof_type_t);
- case TYPE_BITFIELD: return sizeof(bitfield_type_t);
- case TYPE_ERROR: panic("error type found");
- case TYPE_INVALID: panic("invalid type found");
- }
- panic("unknown type found");
-}
-
/**
* Duplicates a type.
*
*/
type_t *duplicate_type(const type_t *type)
{
- size_t size = get_type_struct_size(type);
+ size_t size = get_type_struct_size(type->kind);
type_t *copy = obstack_alloc(type_obst, size);
memcpy(copy, type, size);
assert(!is_typeref(type));
switch (type->kind) {
- case TYPE_POINTER: return true;
- case TYPE_BUILTIN: return is_type_scalar(type->builtin.real_type);
- default: break;
+ case TYPE_POINTER: return true;
+ case TYPE_BUILTIN: return is_type_scalar(type->builtin.real_type);
+ default: break;
}
return is_type_arithmetic(type);
return identify_new_type(type);
}
+static entity_t *pack_bitfield_members_big_endian(il_size_t *struct_offset,
+ il_alignment_t *struct_alignment, bool packed, entity_t *first)
+{
+ type_t *current_base_type = NULL;
+ il_size_t offset = *struct_offset;
+ il_alignment_t alignment = *struct_alignment;
+ size_t bit_offset = 0;
+
+ if (packed)
+ panic("packed bitfields on big-endian arch not supported yet");
+
+ entity_t *member;
+ for (member = first; member != NULL; member = member->base.next) {
+ if (member->kind != ENTITY_COMPOUND_MEMBER)
+ continue;
+
+ type_t *type = member->declaration.type;
+ if (type->kind != TYPE_BITFIELD)
+ break;
+
+ size_t bit_size = type->bitfield.bit_size;
+ type_t *base_type = skip_typeref(type->bitfield.base_type);
+
+ /* see if we need to start a new "bucket" */
+ if (base_type != current_base_type || bit_size > bit_offset) {
+ if (current_base_type != NULL)
+ offset += get_type_size(current_base_type);
+
+ current_base_type = 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;
+ offset = (offset + base_alignment-1) & ~alignment_mask;
+ bit_offset = get_type_size(base_type) * BITS_PER_BYTE;
+ assert(bit_offset >= bit_size);
+ }
+
+ bit_offset -= bit_size;
+ member->compound_member.offset = offset;
+ member->compound_member.bit_offset = bit_offset;
+ }
+
+ if (current_base_type != NULL)
+ offset += get_type_size(current_base_type);
+
+ *struct_offset = offset;
+ *struct_alignment = alignment;
+ return member;
+}
+
static entity_t *pack_bitfield_members(il_size_t *struct_offset,
il_alignment_t *struct_alignment,
bool packed, entity_t *first)
entity_t *member;
for (member = first; member != NULL; member = member->base.next) {
if (member->kind != ENTITY_COMPOUND_MEMBER)
- break;
+ continue;
type_t *type = member->declaration.type;
if (type->kind != TYPE_BITFIELD)
*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);
}
if (skipped->kind == TYPE_BITFIELD) {
- entry = pack_bitfield_members(&offset, &alignment,
- compound->packed, entry);
+ if (byte_order_big_endian) {
+ entry = pack_bitfield_members_big_endian(&offset, &alignment,
+ compound->packed,
+ entry);
+ } else {
+ entry = pack_bitfield_members(&offset, &alignment,
+ compound->packed, entry);
+ }
continue;
}
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->alignment = alignment;
}
+static function_parameter_t *allocate_parameter(type_t *const type)
+{
+ function_parameter_t *const param
+ = obstack_alloc(type_obst, sizeof(*param));
+ memset(param, 0, sizeof(*param));
+ param->type = type;
+ return param;
+}
+
+type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
+ type_t *argument_type2)
+{
+ function_parameter_t *const parameter2 = allocate_parameter(argument_type2);
+ function_parameter_t *const parameter1 = allocate_parameter(argument_type1);
+ parameter1->next = parameter2;
+
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type->function.return_type = return_type;
+ type->function.parameters = parameter1;
+ type->function.linkage = LINKAGE_C;
+
+ return identify_new_type(type);
+}
+
+type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
+{
+ function_parameter_t *const parameter = allocate_parameter(argument_type);
+
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type->function.return_type = return_type;
+ type->function.parameters = parameter;
+ type->function.linkage = LINKAGE_C;
+
+ return identify_new_type(type);
+}
+
+type_t *make_function_1_type_variadic(type_t *return_type,
+ type_t *argument_type)
+{
+ function_parameter_t *const parameter = allocate_parameter(argument_type);
+
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type->function.return_type = return_type;
+ type->function.parameters = parameter;
+ type->function.variadic = true;
+ type->function.linkage = LINKAGE_C;
+
+ return identify_new_type(type);
+}
+
+type_t *make_function_0_type(type_t *return_type)
+{
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type->function.return_type = return_type;
+ type->function.parameters = NULL;
+ type->function.linkage = LINKAGE_C;
+
+ return identify_new_type(type);
+}
+
+type_t *make_function_type(type_t *return_type, int n_types,
+ type_t *const *argument_types,
+ decl_modifiers_t modifiers)
+{
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type->function.return_type = return_type;
+ type->function.modifiers |= modifiers;
+ type->function.linkage = LINKAGE_C;
+
+ function_parameter_t *last = NULL;
+ for (int i = 0; i < n_types; ++i) {
+ function_parameter_t *parameter = allocate_parameter(argument_types[i]);
+ if (last == NULL) {
+ type->function.parameters = parameter;
+ } else {
+ last->next = parameter;
+ }
+ last = parameter;
+ }
+
+ return identify_new_type(type);
+}
+
/**
* Debug helper. Prints the given type to stdout.
*/