harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

qtype.c (7114B)


      1 #include <assert.h>
      2 #include <inttypes.h>
      3 #include <stdlib.h>
      4 #include <stdio.h>
      5 #include "gen.h"
      6 #include "qbe.h"
      7 #include "type_store.h"
      8 #include "types.h"
      9 #include "util.h"
     10 
     11 static int
     12 sf_compar(const void *_a, const void *_b)
     13 {
     14 	const struct struct_field **a = (const struct struct_field **)_a;
     15 	const struct struct_field **b = (const struct struct_field **)_b;
     16 	return (int)(*a)->offset - (int)(*b)->offset;
     17 }
     18 
     19 static const struct qbe_type *
     20 tagged_qtype(struct gen_context *ctx, const struct type *type)
     21 {
     22 	struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def));
     23 	def->kind = Q_TYPE;
     24 	def->name = gen_name(&ctx->id, "tags.%d");
     25 	def->exported = false;
     26 	def->type.stype = Q__AGGREGATE;
     27 	def->type.base = NULL;
     28 	def->type.name = def->name;
     29 	def->type.size = type->size - type->align;
     30 
     31 	struct qbe_field *field = &def->type.fields;
     32 	struct qbe_field **next = &field->next;
     33 	for (const struct type_tagged_union *tu = &type->tagged;
     34 			tu; tu = tu->next) {
     35 		if (tu->type->size == 0) {
     36 			if (!tu->next && *next) {
     37 				free(*next);
     38 				*next = NULL;
     39 			}
     40 			continue;
     41 		}
     42 		field->type = qtype_lookup(ctx, tu->type, true);
     43 		field->count = 1;
     44 		if (tu->next) {
     45 			field->next = xcalloc(1, sizeof(struct qbe_field));
     46 			next = &field->next;
     47 			field = field->next;
     48 		}
     49 	}
     50 
     51 	qbe_append_def(ctx->out, def);
     52 	return &def->type;
     53 }
     54 
     55 static const struct qbe_type *
     56 aggregate_lookup(struct gen_context *ctx, const struct type *type)
     57 {
     58 	for (struct qbe_def *def = ctx->out->defs; def; def = def->next) {
     59 		if (def->kind == Q_TYPE && def->type.base == type) {
     60 			return &def->type;
     61 		}
     62 	}
     63 
     64 	struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def));
     65 	def->kind = Q_TYPE;
     66 	def->name = gen_name(&ctx->id, "type.%d");
     67 	def->type.stype = Q__AGGREGATE;
     68 	def->type.base = type;
     69 	def->type.name = def->name;
     70 
     71 	const struct type *final = type_dealias(type);
     72 	assert((final->storage == STORAGE_STRUCT && final->struct_union.packed)
     73 			|| type->size == SIZE_UNDEFINED
     74 			|| type->size == 0
     75 			|| type->size % type->align == 0);
     76 
     77 	struct qbe_field *field = &def->type.fields;
     78 	switch (type->storage) {
     79 	case STORAGE_ARRAY:
     80 		if (type->array.length == SIZE_UNDEFINED) {
     81 			return &qbe_long; // Special case
     82 		}
     83 		field->count = type->array.length;
     84 		field->type = qtype_lookup(ctx, type->array.members, true);
     85 		break;
     86 	case STORAGE_STRING:
     87 		// XXX: This assertion does not hold for all architectures
     88 		assert(ctx->arch.ptr->stype == ctx->arch.sz->stype);
     89 		field->type = ctx->arch.ptr;
     90 		field->count = 3;
     91 		break;
     92 	case STORAGE_SLICE:
     93 		// XXX: This assertion does not hold for all architectures
     94 		assert(ctx->arch.ptr->stype == ctx->arch.sz->stype);
     95 		field->type = ctx->arch.ptr;
     96 		field->count = 3;
     97 		break;
     98 	case STORAGE_STRUCT:
     99 	case STORAGE_UNION:
    100 		if (!type->struct_union.c_compat) {
    101 			field->type = NULL;
    102 			field->count = type->size;
    103 			break;
    104 		}
    105 		size_t n = 0;
    106 		for (struct struct_field *tfield = type->struct_union.fields;
    107 				tfield; tfield = tfield->next) {
    108 			++n;
    109 		}
    110 		struct struct_field **tfields =
    111 			xcalloc(sizeof(struct struct_field *), n);
    112 		size_t i = 0;
    113 		for (struct struct_field *tfield = type->struct_union.fields;
    114 				tfield; tfield = tfield->next, ++i) {
    115 			tfields[i] = tfield;
    116 		}
    117 		qsort(tfields, n, sizeof(struct struct_field *), sf_compar);
    118 		for (size_t i = 0; i < n; ++i) {
    119 			struct struct_field *tfield = tfields[i];
    120 			field->type = qtype_lookup(ctx, tfield->type, true);
    121 			field->count = 1;
    122 
    123 			if (i + 1 < n) {
    124 				field->next = xcalloc(1, sizeof(struct qbe_field));
    125 				field = field->next;
    126 			}
    127 		}
    128 		free(tfields);
    129 		break;
    130 	case STORAGE_TUPLE:
    131 		for (const struct type_tuple *tuple = &type->tuple;
    132 				tuple; tuple = tuple->next) {
    133 			field->type = qtype_lookup(ctx, tuple->type, true);
    134 			field->count = 1;
    135 
    136 			if (tuple->next) {
    137 				field->next = xcalloc(1, sizeof(struct qbe_field));
    138 				field = field->next;
    139 			}
    140 		}
    141 		break;
    142 	case STORAGE_TAGGED:
    143 		field->type = &qbe_word; // XXX: ARCH
    144 		field->count = 1;
    145 		if (type->size != builtin_type_uint.size) {
    146 			field->next = xcalloc(1, sizeof(struct qbe_field));
    147 			field = field->next;
    148 			field->type = tagged_qtype(ctx, type);
    149 			field->count = 1;
    150 		}
    151 		break;
    152 	case STORAGE_ENUM:
    153 	case STORAGE_ERROR:
    154 	case STORAGE_ALIAS:
    155 	case STORAGE_CHAR:
    156 	case STORAGE_I8:
    157 	case STORAGE_U8:
    158 	case STORAGE_I16:
    159 	case STORAGE_U16:
    160 	case STORAGE_BOOL:
    161 	case STORAGE_I32:
    162 	case STORAGE_U32:
    163 	case STORAGE_RCONST:
    164 	case STORAGE_RUNE:
    165 	case STORAGE_INT:
    166 	case STORAGE_UINT:
    167 	case STORAGE_I64:
    168 	case STORAGE_U64:
    169 	case STORAGE_ICONST:
    170 	case STORAGE_SIZE:
    171 	case STORAGE_UINTPTR:
    172 	case STORAGE_POINTER:
    173 	case STORAGE_NULL:
    174 	case STORAGE_F32:
    175 	case STORAGE_F64:
    176 	case STORAGE_FCONST:
    177 	case STORAGE_VALIST:
    178 	case STORAGE_VOID:
    179 	case STORAGE_FUNCTION:
    180 		abort(); // Invariant
    181 	}
    182 
    183 	qbe_append_def(ctx->out, def);
    184 	return &def->type;
    185 }
    186 
    187 const struct qbe_type *
    188 qtype_lookup(struct gen_context *ctx,
    189 		const struct type *type,
    190 		bool xtype) {
    191 	switch (type->storage) {
    192 	case STORAGE_U8:
    193 	case STORAGE_I8:
    194 	case STORAGE_CHAR:
    195 	case STORAGE_BOOL:
    196 		return xtype ? &qbe_byte : &qbe_word;
    197 	case STORAGE_I16:
    198 	case STORAGE_U16:
    199 		return xtype ? &qbe_half : &qbe_word;
    200 	case STORAGE_I32:
    201 	case STORAGE_U32:
    202 	case STORAGE_INT:
    203 	case STORAGE_UINT:
    204 	case STORAGE_RUNE:
    205 		return &qbe_word;
    206 	case STORAGE_U64:
    207 	case STORAGE_I64:
    208 		return &qbe_long;
    209 	case STORAGE_SIZE:
    210 		return ctx->arch.sz;
    211 	case STORAGE_UINTPTR:
    212 	case STORAGE_POINTER:
    213 	case STORAGE_NULL:
    214 		return ctx->arch.ptr;
    215 	case STORAGE_F32:
    216 		return &qbe_single;
    217 	case STORAGE_F64:
    218 		return &qbe_double;
    219 	case STORAGE_ENUM:
    220 	case STORAGE_ALIAS:
    221 		return qtype_lookup(ctx, type->alias.type, xtype);
    222 	case STORAGE_ARRAY:
    223 	case STORAGE_SLICE:
    224 	case STORAGE_STRING:
    225 	case STORAGE_STRUCT:
    226 	case STORAGE_TAGGED:
    227 	case STORAGE_TUPLE:
    228 	case STORAGE_UNION:
    229 		return aggregate_lookup(ctx, type);
    230 	case STORAGE_FUNCTION:
    231 		return ctx->arch.ptr;
    232 	case STORAGE_VALIST:
    233 		return ctx->arch.ptr;
    234 	case STORAGE_ERROR:
    235 	case STORAGE_VOID:
    236 		abort(); // Invariant
    237 	case STORAGE_FCONST:
    238 	case STORAGE_ICONST:
    239 	case STORAGE_RCONST:
    240 		return qtype_lookup(ctx, lower_const(type, NULL), xtype);
    241 	}
    242 	abort(); // Invariant
    243 }
    244 
    245 bool
    246 type_is_aggregate(const struct type *type)
    247 {
    248 	switch (type->storage) {
    249 	case STORAGE_BOOL:
    250 	case STORAGE_CHAR:
    251 	case STORAGE_ENUM:
    252 	case STORAGE_F32:
    253 	case STORAGE_F64:
    254 	case STORAGE_I16:
    255 	case STORAGE_I32:
    256 	case STORAGE_I64:
    257 	case STORAGE_I8:
    258 	case STORAGE_INT:
    259 	case STORAGE_POINTER:
    260 	case STORAGE_NULL:
    261 	case STORAGE_RUNE:
    262 	case STORAGE_SIZE:
    263 	case STORAGE_U16:
    264 	case STORAGE_U32:
    265 	case STORAGE_U64:
    266 	case STORAGE_U8:
    267 	case STORAGE_UINT:
    268 	case STORAGE_UINTPTR:
    269 	case STORAGE_VOID:
    270 		return false;
    271 	case STORAGE_FUNCTION:
    272 		// Special case
    273 		return false;
    274 	case STORAGE_ALIAS:
    275 		return type_is_aggregate(type->alias.type);
    276 	case STORAGE_ARRAY:
    277 	case STORAGE_SLICE:
    278 	case STORAGE_STRING:
    279 	case STORAGE_STRUCT:
    280 	case STORAGE_TAGGED:
    281 	case STORAGE_TUPLE:
    282 	case STORAGE_UNION:
    283 	case STORAGE_VALIST:
    284 		return true;
    285 	case STORAGE_FCONST:
    286 	case STORAGE_ICONST:
    287 	case STORAGE_RCONST:
    288 		lower_const(type, NULL);
    289 		return false;
    290 	case STORAGE_ERROR:
    291 		assert(0); // Invariant
    292 	}
    293 	assert(0); // Unreachable
    294 }