+unsigned get_type_size(type_t *type)
+{
+ switch (type->kind) {
+ case TYPE_INVALID:
+ break;
+ case TYPE_ERROR:
+ return 0;
+ case TYPE_ATOMIC:
+ 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);
+ 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_POINTER:
+ /* TODO: make configurable by backend */
+ return 4;
+ case TYPE_ARRAY: {
+ /* TODO: correct if element_type is aligned? */
+ il_size_t element_size = get_type_size(type->array.element_type);
+ return type->array.size * element_size;
+ }
+ case TYPE_BITFIELD:
+ return 0;
+ case TYPE_BUILTIN:
+ return get_type_size(type->builtin.real_type);
+ case TYPE_TYPEDEF:
+ return get_type_size(type->typedeft.typedefe->type);
+ case TYPE_TYPEOF:
+ if (type->typeoft.typeof_type) {
+ return get_type_size(type->typeoft.typeof_type);
+ } else {
+ return get_type_size(type->typeoft.expression->base.type);
+ }
+ }
+ panic("invalid type in get_type_size");
+}
+
+unsigned get_type_alignment(type_t *type)
+{
+ switch (type->kind) {
+ case TYPE_INVALID:
+ break;
+ 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_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:
+ /* what is correct here? */
+ return 4;
+ case TYPE_REFERENCE:
+ case TYPE_POINTER:
+ /* TODO: make configurable by backend */
+ return 4;
+ case TYPE_ARRAY:
+ return get_type_alignment(type->array.element_type);
+ case TYPE_BITFIELD:
+ return 0;
+ case TYPE_BUILTIN:
+ return get_type_alignment(type->builtin.real_type);
+ case TYPE_TYPEDEF: {
+ il_alignment_t alignment
+ = get_type_alignment(type->typedeft.typedefe->type);
+ if (type->typedeft.typedefe->alignment > alignment)
+ alignment = type->typedeft.typedefe->alignment;
+
+ return alignment;
+ }
+ case TYPE_TYPEOF:
+ if (type->typeoft.typeof_type) {
+ return get_type_alignment(type->typeoft.typeof_type);
+ } else {
+ return get_type_alignment(type->typeoft.expression->base.type);
+ }
+ }
+ panic("invalid type in get_type_alignment");
+}
+
+decl_modifiers_t get_type_modifiers(const type_t *type)
+{
+ switch(type->kind) {
+ case TYPE_INVALID:
+ case TYPE_ERROR:
+ break;
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION:
+ return type->compound.compound->modifiers;
+ case TYPE_FUNCTION:
+ return type->function.modifiers;
+ case TYPE_ENUM:
+ case TYPE_ATOMIC:
+ case TYPE_COMPLEX:
+ case TYPE_IMAGINARY:
+ case TYPE_REFERENCE:
+ case TYPE_POINTER:
+ case TYPE_BITFIELD:
+ case TYPE_ARRAY:
+ return 0;
+ case TYPE_BUILTIN:
+ return get_type_modifiers(type->builtin.real_type);
+ case TYPE_TYPEDEF: {
+ decl_modifiers_t modifiers = type->typedeft.typedefe->modifiers;
+ modifiers |= get_type_modifiers(type->typedeft.typedefe->type);
+ return modifiers;
+ }
+ case TYPE_TYPEOF:
+ if (type->typeoft.typeof_type) {
+ return get_type_modifiers(type->typeoft.typeof_type);
+ } else {
+ return get_type_modifiers(type->typeoft.expression->base.type);
+ }
+ }
+ panic("invalid type found in get_type_modifiers");
+}
+
+type_qualifiers_t get_type_qualifier(const type_t *type, bool skip_array_type)
+{
+ type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
+
+ while (true) {
+ switch (type->base.kind) {
+ case TYPE_ERROR:
+ return TYPE_QUALIFIER_NONE;
+ case TYPE_TYPEDEF:
+ qualifiers |= type->base.qualifiers;
+ const typedef_type_t *typedef_type = &type->typedeft;
+ if (typedef_type->resolved_type != NULL)
+ type = typedef_type->resolved_type;
+ else
+ type = typedef_type->typedefe->type;
+ continue;
+ case TYPE_TYPEOF:
+ type = type->typeoft.typeof_type;
+ continue;
+ case TYPE_ARRAY:
+ if (skip_array_type) {
+ type = type->array.element_type;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ return type->base.qualifiers | qualifiers;
+}
+
+unsigned get_atomic_type_size(atomic_type_kind_t kind)
+{
+ assert(kind <= ATOMIC_TYPE_LAST);
+ return atomic_type_properties[kind].size;
+}
+
+unsigned get_atomic_type_alignment(atomic_type_kind_t kind)
+{
+ assert(kind <= ATOMIC_TYPE_LAST);
+ return atomic_type_properties[kind].alignment;
+}
+
+unsigned get_atomic_type_flags(atomic_type_kind_t kind)
+{
+ assert(kind <= ATOMIC_TYPE_LAST);
+ return atomic_type_properties[kind].flags;
+}
+
+atomic_type_kind_t get_intptr_kind(void)
+{
+ if (machine_size <= 32)
+ return ATOMIC_TYPE_INT;
+ else if (machine_size <= 64)
+ return ATOMIC_TYPE_LONG;
+ else
+ return ATOMIC_TYPE_LONGLONG;
+}
+
+atomic_type_kind_t get_uintptr_kind(void)
+{
+ if (machine_size <= 32)
+ return ATOMIC_TYPE_UINT;
+ else if (machine_size <= 64)
+ return ATOMIC_TYPE_ULONG;
+ else
+ return ATOMIC_TYPE_ULONGLONG;
+}
+
+/**
+ * Find the atomic type kind representing a given size (signed).
+ */
+atomic_type_kind_t find_signed_int_atomic_type_kind_for_size(unsigned size)
+{
+ static atomic_type_kind_t kinds[32];
+
+ assert(size < 32);
+ atomic_type_kind_t kind = kinds[size];
+ if (kind == ATOMIC_TYPE_INVALID) {
+ static const atomic_type_kind_t possible_kinds[] = {
+ ATOMIC_TYPE_SCHAR,
+ ATOMIC_TYPE_SHORT,
+ ATOMIC_TYPE_INT,
+ ATOMIC_TYPE_LONG,
+ ATOMIC_TYPE_LONGLONG
+ };
+ for (size_t i = 0; i < lengthof(possible_kinds); ++i) {
+ if (get_atomic_type_size(possible_kinds[i]) == size) {
+ kind = possible_kinds[i];
+ break;
+ }
+ }
+ kinds[size] = kind;
+ }
+ return kind;
+}
+
+/**
+ * Find the atomic type kind representing a given size (signed).
+ */
+atomic_type_kind_t find_unsigned_int_atomic_type_kind_for_size(unsigned size)
+{
+ static atomic_type_kind_t kinds[32];
+
+ assert(size < 32);
+ atomic_type_kind_t kind = kinds[size];
+ if (kind == ATOMIC_TYPE_INVALID) {
+ static const atomic_type_kind_t possible_kinds[] = {
+ ATOMIC_TYPE_UCHAR,
+ ATOMIC_TYPE_USHORT,
+ ATOMIC_TYPE_UINT,
+ ATOMIC_TYPE_ULONG,
+ ATOMIC_TYPE_ULONGLONG
+ };
+ for (size_t i = 0; i < lengthof(possible_kinds); ++i) {
+ if (get_atomic_type_size(possible_kinds[i]) == size) {
+ kind = possible_kinds[i];
+ break;
+ }
+ }
+ kinds[size] = kind;
+ }
+ return kind;
+}
+