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 }