harec

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

qtype.c (7146B)


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