/**
* Creates a Firm type for a complex type
*/
-static ir_type *create_complex_type(const complex_type_t *type)
+static ir_type *create_complex_type(const atomic_type_t *type)
{
atomic_type_kind_t kind = type->akind;
ir_mode *mode = atomic_modes[kind];
/**
* Creates a Firm type for an imaginary type
*/
-static ir_type *create_imaginary_type(imaginary_type_t *type)
+static ir_type *create_imaginary_type(const atomic_type_t *type)
{
- return create_atomic_type(type->akind, (const type_t*) type);
+ return create_atomic_type(type->akind, (const type_t*)type);
}
/**
static ir_type *create_enum_type(enum_type_t *const type)
{
- type->base.firm_type = ir_type_int;
+ type->base.base.firm_type = ir_type_int;
ir_mode *const mode = mode_int;
ir_tarval *const one = get_mode_one(mode);
constant_folding = constant_folding_old;
- return create_atomic_type(type->akind, (const type_t*) type);
+ return create_atomic_type(type->base.akind, (const type_t*) type);
}
static ir_type *get_ir_type_incomplete(type_t *type)
firm_type = create_atomic_type(type->atomic.akind, type);
break;
case TYPE_COMPLEX:
- firm_type = create_complex_type(&type->complex);
+ firm_type = create_complex_type(&type->atomic);
break;
case TYPE_IMAGINARY:
- firm_type = create_imaginary_type(&type->imaginary);
+ firm_type = create_imaginary_type(&type->atomic);
break;
case TYPE_FUNCTION:
firm_type = create_method_type(&type->function, false);
return orig_type;
}
- if (type->kind == TYPE_ATOMIC) {
+ if (type->kind == TYPE_ATOMIC || type->kind == TYPE_ENUM) {
type_t *copy = duplicate_type(type);
copy->atomic.akind = akind;
return identify_new_type(copy);
- } else if (type->kind == TYPE_ENUM) {
- type_t *copy = duplicate_type(type);
- copy->enumt.akind = akind;
- return identify_new_type(copy);
} else if (is_type_pointer(type)) {
source_position_t const *const pos = &attribute->source_position;
warningf(WARN_OTHER, pos, "__attribute__((mode)) on pointers not implemented yet (ignored)");
props->struct_alignment = props->alignment;
}
+/**
+ * Copy atomic type properties except the integer conversion rank
+ */
+static void copy_typeprops(atomic_type_properties_t *dest,
+ const atomic_type_properties_t *src)
+{
+ dest->size = src->size;
+ dest->alignment = src->alignment;
+ dest->struct_alignment = src->struct_alignment;
+ dest->flags = src->flags;
+}
+
static void init_types_and_adjust(void)
{
const backend_params *be_params = be_get_backend_param();
/* stuff decided after processing operating system specifics and
* commandline flags */
- props[ATOMIC_TYPE_WCHAR_T] = props[wchar_atomic_kind];
if (char_is_signed) {
props[ATOMIC_TYPE_CHAR].flags |= ATOMIC_TYPE_FLAG_SIGNED;
} else {
props[ATOMIC_TYPE_CHAR].flags &= ~ATOMIC_TYPE_FLAG_SIGNED;
}
+ /* copy over wchar_t properties (including rank) */
+ props[ATOMIC_TYPE_WCHAR_T] = props[wchar_atomic_kind];
/* initialize defaults for unsupported types */
if (type_long_long == NULL) {
- props[ATOMIC_TYPE_LONGLONG] = props[ATOMIC_TYPE_LONG];
- }
- if (type_long_double == NULL) {
- props[ATOMIC_TYPE_LONG_DOUBLE] = props[ATOMIC_TYPE_DOUBLE];
+ copy_typeprops(&props[ATOMIC_TYPE_LONGLONG], &props[ATOMIC_TYPE_LONG]);
}
if (type_unsigned_long_long == NULL) {
- props[ATOMIC_TYPE_ULONGLONG] = props[ATOMIC_TYPE_ULONG];
+ copy_typeprops(&props[ATOMIC_TYPE_ULONGLONG],
+ &props[ATOMIC_TYPE_ULONG]);
+ }
+ if (type_long_double == NULL) {
+ copy_typeprops(&props[ATOMIC_TYPE_LONG_DOUBLE],
+ &props[ATOMIC_TYPE_DOUBLE]);
}
/* initialize firm pointer modes */
mangle_type(type->element_type);
}
-static void mangle_complex_type(const complex_type_t *type)
+static void mangle_complex_type(const atomic_type_t *type)
{
obstack_1grow(&obst, 'C');
obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
}
-static void mangle_imaginary_type(const imaginary_type_t *type)
+static void mangle_imaginary_type(const atomic_type_t *type)
{
obstack_1grow(&obst, 'G');
obstack_1grow(&obst, get_atomic_type_mangle(type->akind));
mangle_array_type(&type->array);
return;
case TYPE_COMPLEX:
- mangle_complex_type(&type->complex);
+ mangle_complex_type(&type->atomic);
return;
case TYPE_IMAGINARY:
- mangle_imaginary_type(&type->imaginary);
+ mangle_imaginary_type(&type->atomic);
return;
case TYPE_ERROR:
panic("error type encountered while mangling");
stack_pop_to(&label_stack, new_top);
}
-static int get_akind_rank(atomic_type_kind_t akind)
+static atomic_type_kind_t get_akind(const type_t *type)
{
- return (int) akind;
-}
-
-/**
- * Return the type rank for an atomic type.
- */
-static int get_rank(const type_t *type)
-{
- assert(!is_typeref(type));
- if (type->kind == TYPE_ENUM)
- return get_akind_rank(type->enumt.akind);
-
- assert(type->kind == TYPE_ATOMIC);
- return get_akind_rank(type->atomic.akind);
+ assert(type->kind == TYPE_ATOMIC || type->kind == TYPE_COMPLEX
+ || type->kind == TYPE_IMAGINARY || type->kind == TYPE_ENUM);
+ return type->atomic.akind;
}
/**
*/
static type_t *promote_integer(type_t *type)
{
- if (get_rank(type) < get_akind_rank(ATOMIC_TYPE_INT))
+ if (get_akind_rank(get_akind(type)) < get_akind_rank(ATOMIC_TYPE_INT))
type = type_int;
return type;
entity->base.parent_scope = current_scope;
}
- type_t *const type = allocate_type_zero(TYPE_ENUM);
- type->enumt.enume = &entity->enume;
- type->enumt.akind = ATOMIC_TYPE_INT;
+ type_t *const type = allocate_type_zero(TYPE_ENUM);
+ type->enumt.enume = &entity->enume;
+ type->enumt.base.akind = ATOMIC_TYPE_INT;
if (token.kind == '{') {
if (symbol != NULL) {
}
if (type_specifiers & SPECIFIER_COMPLEX) {
- type = allocate_type_zero(TYPE_COMPLEX);
- type->complex.akind = atomic_type;
+ type = allocate_type_zero(TYPE_COMPLEX);
} else if (type_specifiers & SPECIFIER_IMAGINARY) {
- type = allocate_type_zero(TYPE_IMAGINARY);
- type->imaginary.akind = atomic_type;
+ type = allocate_type_zero(TYPE_IMAGINARY);
} else {
- type = allocate_type_zero(TYPE_ATOMIC);
- type->atomic.akind = atomic_type;
+ type = allocate_type_zero(TYPE_ATOMIC);
}
+ type->atomic.akind = atomic_type;
newtype = true;
} else if (type_specifiers != 0) {
errorf(&specifiers->source_position, "multiple datatypes in declaration");
if (type_left == type_right)
return type_left;
- bool const signed_left = is_type_signed(type_left);
- bool const signed_right = is_type_signed(type_right);
- int const rank_left = get_rank(type_left);
- int const rank_right = get_rank(type_right);
+ bool const signed_left = is_type_signed(type_left);
+ bool const signed_right = is_type_signed(type_right);
+ unsigned const rank_left = get_akind_rank(get_akind(type_left));
+ unsigned const rank_right = get_akind_rank(get_akind(type_right));
if (signed_left == signed_right)
return rank_left >= rank_right ? type_left : type_right;
- int s_rank;
- int u_rank;
+ unsigned s_rank;
+ unsigned u_rank;
+ atomic_type_kind_t s_akind;
+ atomic_type_kind_t u_akind;
type_t *s_type;
type_t *u_type;
if (signed_left) {
- s_rank = rank_left;
s_type = type_left;
- u_rank = rank_right;
u_type = type_right;
} else {
- s_rank = rank_right;
s_type = type_right;
- u_rank = rank_left;
u_type = type_left;
}
+ s_akind = get_akind(s_type);
+ u_akind = get_akind(u_type);
+ s_rank = get_akind_rank(s_akind);
+ u_rank = get_akind_rank(u_akind);
if (u_rank >= s_rank)
return u_type;
- /* casting rank to atomic_type_kind is a bit hacky, but makes things
- * easier here... */
- if (get_atomic_type_size((atomic_type_kind_t) s_rank)
- > get_atomic_type_size((atomic_type_kind_t) u_rank))
+ if (get_atomic_type_size(s_akind) > get_atomic_type_size(u_akind))
return s_type;
- switch (s_rank) {
- case ATOMIC_TYPE_INT: return type_unsigned_int;
- case ATOMIC_TYPE_LONG: return type_unsigned_long;
- case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long;
+ switch (s_akind) {
+ case ATOMIC_TYPE_INT: return type_unsigned_int;
+ case ATOMIC_TYPE_LONG: return type_unsigned_long;
+ case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long;
- default: panic("invalid atomic type");
+ default: panic("invalid atomic type");
}
}
type_t * type = skip_typeref(expr->base.type);
if (is_type_integer(type)) {
type = promote_integer(type);
- if (get_rank(type) >= get_akind_rank(ATOMIC_TYPE_LONG)) {
+ if (get_akind_rank(get_akind(type)) >= get_akind_rank(ATOMIC_TYPE_LONG)) {
warningf(WARN_TRADITIONAL, &expr->base.source_position, "'%T' switch expression not converted to '%T' in ISO C", type, type_int);
}
} else if (is_type_valid(type)) {
{
static const size_t sizes[] = {
[TYPE_ATOMIC] = sizeof(atomic_type_t),
- [TYPE_COMPLEX] = sizeof(complex_type_t),
- [TYPE_IMAGINARY] = sizeof(imaginary_type_t),
[TYPE_COMPOUND_STRUCT] = sizeof(compound_type_t),
[TYPE_COMPOUND_UNION] = sizeof(compound_type_t),
[TYPE_ENUM] = sizeof(enum_type_t),
[ATOMIC_TYPE_VOID] = {
.size = 0,
.alignment = 0,
- .flags = ATOMIC_TYPE_FLAG_NONE
+ .flags = ATOMIC_TYPE_FLAG_NONE,
+ .rank = 0,
},
- [ATOMIC_TYPE_WCHAR_T] = {
- .size = (unsigned)-1,
- .alignment = (unsigned)-1,
- .flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ [ATOMIC_TYPE_BOOL] = {
+ .size = 1,
+ .alignment = 1,
+ .flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = 1,
},
[ATOMIC_TYPE_CHAR] = {
.size = 1,
.alignment = 1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = 2,
},
[ATOMIC_TYPE_SCHAR] = {
.size = 1,
.alignment = 1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
| ATOMIC_TYPE_FLAG_SIGNED,
+ .rank = 2,
},
[ATOMIC_TYPE_UCHAR] = {
.size = 1,
.alignment = 1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = 2,
},
[ATOMIC_TYPE_SHORT] = {
.size = 2,
.alignment = 2,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
- | ATOMIC_TYPE_FLAG_SIGNED
+ | ATOMIC_TYPE_FLAG_SIGNED,
+ .rank = 3,
},
[ATOMIC_TYPE_USHORT] = {
.size = 2,
.alignment = 2,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = 3,
},
[ATOMIC_TYPE_INT] = {
.size = (unsigned) -1,
.alignment = (unsigned) -1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
| ATOMIC_TYPE_FLAG_SIGNED,
+ .rank = 4,
},
[ATOMIC_TYPE_UINT] = {
.size = (unsigned) -1,
.alignment = (unsigned) -1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = 4,
},
[ATOMIC_TYPE_LONG] = {
.size = (unsigned) -1,
.alignment = (unsigned) -1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC
| ATOMIC_TYPE_FLAG_SIGNED,
+ .rank = 5,
},
[ATOMIC_TYPE_ULONG] = {
.size = (unsigned) -1,
.alignment = (unsigned) -1,
.flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
- },
- [ATOMIC_TYPE_BOOL] = {
- .size = 1,
- .alignment = 1,
- .flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = 5,
},
[ATOMIC_TYPE_FLOAT] = {
.size = 4,
.alignment = 4,
.flags = ATOMIC_TYPE_FLAG_FLOAT | ATOMIC_TYPE_FLAG_ARITHMETIC
| ATOMIC_TYPE_FLAG_SIGNED,
+ .rank = 0,
},
[ATOMIC_TYPE_DOUBLE] = {
.size = 8,
.alignment = 8,
.flags = ATOMIC_TYPE_FLAG_FLOAT | ATOMIC_TYPE_FLAG_ARITHMETIC
| ATOMIC_TYPE_FLAG_SIGNED,
+ .rank = 0,
+ },
+ [ATOMIC_TYPE_WCHAR_T] = {
+ .size = (unsigned)-1,
+ .alignment = (unsigned)-1,
+ .flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC,
+ .rank = (unsigned)-1,
},
};
atomic_type_properties_t pointer_properties = {
*
* @param type The type.
*/
-static void print_complex_type(const complex_type_t *type)
+static void print_complex_type(const atomic_type_t *type)
{
print_type_qualifiers(type->base.qualifiers, QUAL_SEP_END);
print_string("_Complex");
*
* @param type The type.
*/
-static void print_imaginary_type(const imaginary_type_t *type)
+static void print_imaginary_type(const atomic_type_t *type)
{
print_type_qualifiers(type->base.qualifiers, QUAL_SEP_END);
print_string("_Imaginary ");
*/
static void print_type_enum(const enum_type_t *type)
{
- print_type_qualifiers(type->base.qualifiers, QUAL_SEP_END);
+ print_type_qualifiers(type->base.base.qualifiers, QUAL_SEP_END);
print_string("enum ");
enum_t *enume = type->enume;
print_atomic_type(&type->atomic);
return;
case TYPE_COMPLEX:
- print_complex_type(&type->complex);
+ print_complex_type(&type->atomic);
return;
case TYPE_IMAGINARY:
- print_imaginary_type(&type->imaginary);
+ print_imaginary_type(&type->atomic);
return;
case TYPE_COMPOUND_STRUCT:
case TYPE_COMPOUND_UNION:
case TYPE_ENUM:
return true;
case TYPE_ATOMIC:
- return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_ARITHMETIC);
case TYPE_COMPLEX:
- return test_atomic_type_flag(type->complex.akind, ATOMIC_TYPE_FLAG_ARITHMETIC);
case TYPE_IMAGINARY:
- return test_atomic_type_flag(type->imaginary.akind, ATOMIC_TYPE_FLAG_ARITHMETIC);
+ return test_atomic_type_flag(type->atomic.akind, ATOMIC_TYPE_FLAG_ARITHMETIC);
default:
return false;
}
&& !type->array.size_constant;
case TYPE_ATOMIC:
- return type->atomic.akind == ATOMIC_TYPE_VOID;
-
- case TYPE_COMPLEX:
- return type->complex.akind == ATOMIC_TYPE_VOID;
-
case TYPE_IMAGINARY:
- return type->imaginary.akind == ATOMIC_TYPE_VOID;
+ case TYPE_COMPLEX:
+ return type->atomic.akind == ATOMIC_TYPE_VOID;
case TYPE_FUNCTION:
case TYPE_POINTER:
case TYPE_FUNCTION:
return function_types_compatible(&type1->function, &type2->function);
case TYPE_ATOMIC:
- return type1->atomic.akind == type2->atomic.akind;
- case TYPE_COMPLEX:
- return type1->complex.akind == type2->complex.akind;
case TYPE_IMAGINARY:
- return type1->imaginary.akind == type2->imaginary.akind;
+ case TYPE_COMPLEX:
+ return type1->atomic.akind == type2->atomic.akind;
case TYPE_ARRAY:
return array_types_compatible(&type1->array, &type2->array);
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->complex.akind) * 2;
- case TYPE_IMAGINARY:
- return get_atomic_type_size(type->imaginary.akind);
+ return get_atomic_type_size(type->atomic.akind) * 2;
case TYPE_COMPOUND_UNION:
layout_union_type(&type->compound);
return type->compound.compound->size;
case TYPE_COMPOUND_STRUCT:
layout_struct_type(&type->compound);
return type->compound.compound->size;
- case TYPE_ENUM:
- return get_atomic_type_size(type->enumt.akind);
case TYPE_FUNCTION:
return 0; /* non-const (but "address-const") */
case TYPE_REFERENCE:
case TYPE_ERROR:
return 0;
case TYPE_ATOMIC:
- return get_atomic_type_alignment(type->atomic.akind);
- case TYPE_COMPLEX:
- return get_atomic_type_alignment(type->complex.akind);
case TYPE_IMAGINARY:
- return get_atomic_type_alignment(type->imaginary.akind);
+ case TYPE_COMPLEX:
+ case TYPE_ENUM:
+ return get_atomic_type_alignment(type->atomic.akind);
case TYPE_COMPOUND_UNION:
layout_union_type(&type->compound);
return type->compound.compound->alignment;
case TYPE_COMPOUND_STRUCT:
layout_struct_type(&type->compound);
return type->compound.compound->alignment;
- case TYPE_ENUM:
- return get_atomic_type_alignment(type->enumt.akind);
case TYPE_FUNCTION:
/* gcc says 1 here... */
return 1;
* @param akind The kind of the atomic type.
* @param qualifiers Type qualifiers for the new type.
*/
-type_t *make_complex_type(atomic_type_kind_t akind, type_qualifiers_t qualifiers)
+type_t *make_complex_type(atomic_type_kind_t akind,
+ type_qualifiers_t qualifiers)
{
type_t *const type = allocate_type_zero(TYPE_COMPLEX);
type->base.qualifiers = qualifiers;
- type->complex.akind = akind;
+ type->atomic.akind = akind;
return identify_new_type(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 *make_imaginary_type(atomic_type_kind_t akind,
+ type_qualifiers_t qualifiers)
{
type_t *const type = allocate_type_zero(TYPE_IMAGINARY);
type->base.qualifiers = qualifiers;
- type->imaginary.akind = akind;
+ type->atomic.akind = akind;
return identify_new_type(type);
}
return result;
}
-static unsigned hash_complex_type(const complex_type_t *type)
-{
- unsigned some_prime = 27644437;
- unsigned result = type->akind * some_prime;
-
- return result;
-}
-
-static unsigned hash_imaginary_type(const imaginary_type_t *type)
-{
- unsigned some_prime = 27644437;
- unsigned result = type->akind * some_prime;
-
- return result;
-}
-
static unsigned hash_pointer_type(const pointer_type_t *type)
{
return hash_ptr(type->points_to) ^ hash_ptr(type->base_variable);
switch (type->kind) {
case TYPE_ERROR:
return 0;
+ case TYPE_IMAGINARY:
+ case TYPE_COMPLEX:
case TYPE_ATOMIC:
hash = hash_atomic_type(&type->atomic);
break;
- case TYPE_COMPLEX:
- hash = hash_complex_type(&type->complex);
- break;
- case TYPE_IMAGINARY:
- hash = hash_imaginary_type(&type->imaginary);
- break;
case TYPE_ENUM:
hash = hash_enum_type(&type->enumt);
break;
return type1->akind == type2->akind;
}
-static bool complex_types_equal(const complex_type_t *type1,
- const complex_type_t *type2)
-{
- return type1->akind == type2->akind;
-}
-
-static bool imaginary_types_equal(const imaginary_type_t *type1,
- const imaginary_type_t *type2)
-{
- return type1->akind == type2->akind;
-}
-
static bool function_types_equal(const function_type_t *type1,
const function_type_t *type2)
{
/* Hmm, the error type is never equal */
return false;
case TYPE_ATOMIC:
- return atomic_types_equal(&type1->atomic, &type2->atomic);
- case TYPE_COMPLEX:
- return complex_types_equal(&type1->complex, &type2->complex);
case TYPE_IMAGINARY:
- return imaginary_types_equal(&type1->imaginary, &type2->imaginary);
+ case TYPE_COMPLEX:
+ return atomic_types_equal(&type1->atomic, &type2->atomic);
case TYPE_ENUM:
return enum_types_equal(&type1->enumt, &type2->enumt);
case TYPE_COMPOUND_STRUCT:
ir_type *firm_type;
};
+/**
+ * used for atomic types, complex and imaginary
+ */
struct atomic_type_t {
type_base_t base;
atomic_type_kind_t akind;
};
-struct complex_type_t {
- type_base_t base;
- atomic_type_kind_t akind;
-};
-
-struct imaginary_type_t {
- type_base_t base;
- atomic_type_kind_t akind;
-};
-
struct pointer_type_t {
type_base_t base;
type_t *points_to;
};
struct enum_type_t {
- type_base_t base;
- atomic_type_kind_t akind; /**< underlying atomic type */
+ atomic_type_t base;
/** the enum entity. You can find the enum entries by walking the
* enum->base.next list until you don't find ENTITY_ENUM_VALUE entities
* anymore */
type_kind_t kind;
type_base_t base;
atomic_type_t atomic;
- complex_type_t complex;
- imaginary_type_t imaginary;
pointer_type_t pointer;
reference_type_t reference;
array_type_t array;
*/
unsigned struct_alignment;
unsigned flags; /**< type flags from atomic_type_flag_t */
+ unsigned rank; /**< integer conversion rank */
};
extern atomic_type_properties_t atomic_type_properties[ATOMIC_TYPE_LAST+1];
return type->kind != TYPE_ERROR;
}
+/**
+ * return integer conversion rank of an atomic type kind
+ */
+static inline unsigned get_akind_rank(atomic_type_kind_t akind)
+{
+ return atomic_type_properties[akind].rank;
+}
+
/**
* Allocate a type node of given kind and initialize all
* fields with zero.