typedef.c (12152B)
1 #include <assert.h> 2 #include <ctype.h> 3 #include <inttypes.h> 4 #include <math.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include "check.h" 8 #include "expr.h" 9 #include "identifier.h" 10 #include "typedef.h" 11 #include "util.h" 12 13 static const char * 14 storage_to_suffix(enum type_storage storage) 15 { 16 switch (storage) { 17 case STORAGE_CHAR: 18 return ""; 19 case STORAGE_F32: 20 return "f32"; 21 case STORAGE_F64: 22 return "f64"; 23 case STORAGE_FCONST: 24 return ""; 25 case STORAGE_I16: 26 return "i16"; 27 case STORAGE_I32: 28 return "i32"; 29 case STORAGE_I64: 30 return "i64"; 31 case STORAGE_I8: 32 return "i8"; 33 case STORAGE_ICONST: 34 return ""; 35 case STORAGE_INT: 36 return "i"; 37 case STORAGE_SIZE: 38 return "z"; 39 case STORAGE_U16: 40 return "u16"; 41 case STORAGE_U32: 42 return "u32"; 43 case STORAGE_U64: 44 return "u64"; 45 case STORAGE_U8: 46 return "u8"; 47 case STORAGE_UINT: 48 return "u"; 49 case STORAGE_UINTPTR: 50 return "u64: uintptr"; 51 case STORAGE_VALIST: 52 return "valist"; 53 default: 54 assert(0); 55 } 56 } 57 58 static void 59 emit_const(const struct expression *expr, FILE *out) 60 { 61 assert(expr->type == EXPR_CONSTANT); 62 const struct expression_constant *val = &expr->constant; 63 assert(!val->object); 64 switch (type_dealias(expr->result)->storage) { 65 case STORAGE_BOOL: 66 fprintf(out, "%s", val->bval ? "true" : "false"); 67 break; 68 case STORAGE_F32: 69 case STORAGE_F64: 70 case STORAGE_FCONST: 71 { 72 const char *suffix = storage_to_suffix(expr->result->storage); 73 if (isnan(val->fval)) { 74 fprintf(out, "0.0%s / 0.0%s", suffix, suffix); 75 } else if (isinf(val->fval)) { 76 fprintf(out, "%s1.0%s / 0.0%s", 77 (val->fval > 0) ? "" : "-", suffix, suffix); 78 } else { 79 fprintf(out, "%lf%s", val->fval, suffix); 80 } 81 break; 82 } 83 case STORAGE_I16: 84 case STORAGE_I32: 85 case STORAGE_I64: 86 case STORAGE_I8: 87 case STORAGE_ICONST: 88 case STORAGE_INT: 89 fprintf(out, "%" PRIiMAX "%s", val->ival, 90 storage_to_suffix(type_dealias(expr->result)->storage)); 91 break; 92 case STORAGE_NULL: 93 fprintf(out, "null"); 94 break; 95 case STORAGE_SIZE: 96 case STORAGE_U16: 97 case STORAGE_U32: 98 case STORAGE_U64: 99 case STORAGE_U8: 100 case STORAGE_UINT: 101 case STORAGE_UINTPTR: 102 fprintf(out, "%" PRIuMAX "%s", val->uval, 103 storage_to_suffix(type_dealias(expr->result)->storage)); 104 break; 105 case STORAGE_VOID: 106 fprintf(out, "void"); 107 break; 108 case STORAGE_RCONST: 109 case STORAGE_RUNE: 110 fprintf(out, "\'\\U%08" PRIx32 "\'", (uint32_t)val->uval); 111 break; 112 case STORAGE_STRING: 113 fprintf(out, "\""); 114 for (size_t i = 0; i < val->string.len; i += 1) { 115 char c = val->string.value[i]; 116 if (isalnum((unsigned char)c)) { 117 fprintf(out, "%c", c); 118 } else { 119 fprintf(out, "\\x%02X", c); 120 } 121 }; 122 fprintf(out, "\""); 123 break; 124 case STORAGE_ENUM: { 125 const struct type *t = type_dealias(expr->result); 126 char *ident = identifier_unparse(&expr->result->alias.ident); 127 if (t->alias.type->storage == STORAGE_CHAR) { 128 fprintf(out, "%" PRIuMAX, val->uval); 129 } else if (t->alias.type->storage == STORAGE_UINTPTR) { 130 fprintf(out, "%" PRIuMAX ": uintptr", val->uval); 131 } else if (type_is_signed(t->alias.type)) { 132 fprintf(out, "%" PRIiMAX "%s: %s", val->ival, 133 storage_to_suffix(t->alias.type->storage), ident); 134 } else { 135 fprintf(out, "%" PRIuMAX "%s: %s", val->uval, 136 storage_to_suffix(t->alias.type->storage), ident); 137 } 138 free(ident); 139 break; 140 } 141 case STORAGE_TAGGED: 142 emit_const(expr->constant.tagged.value, out); 143 fprintf(out, ": "); 144 emit_type(expr->constant.tagged.tag, out); 145 break; 146 case STORAGE_ARRAY: { 147 fprintf(out, "["); 148 const struct type *t = type_dealias(expr->result); 149 struct array_constant *item = val->array; 150 if (t->array.expandable) { 151 emit_const(item->value, out); 152 fprintf(out, "..."); 153 } else { 154 for (size_t i = 0; i < t->array.length; i += 1) { 155 if (i > 0) { 156 fprintf(out, ","); 157 } 158 emit_const(item->value, out); 159 item = item->next; 160 }; 161 } 162 fprintf(out, "]"); 163 break; 164 } 165 case STORAGE_SLICE: 166 case STORAGE_STRUCT: 167 case STORAGE_TUPLE: 168 case STORAGE_UNION: 169 assert(0); // TODO 170 case STORAGE_ALIAS: 171 case STORAGE_CHAR: 172 case STORAGE_ERROR: 173 case STORAGE_FUNCTION: 174 case STORAGE_POINTER: 175 case STORAGE_VALIST: 176 assert(0); // Invariant 177 } 178 } 179 180 static int 181 field_compar(const void *_a, const void *_b) 182 { 183 const struct struct_field **a = (const struct struct_field **)_a; 184 const struct struct_field **b = (const struct struct_field **)_b; 185 return (*a)->offset - (*b)->offset; 186 } 187 188 static bool 189 emit_struct(const struct type *type, FILE *out) 190 { 191 bool ret = true; 192 size_t n = 0; 193 for (const struct struct_field *f = type->struct_union.fields; 194 f; f = f->next) { 195 ++n; 196 } 197 const struct struct_field **fields = xcalloc( 198 sizeof(const struct struct_field *), n); 199 n = 0; 200 for (const struct struct_field *f = type->struct_union.fields; 201 f; f = f->next) { 202 fields[n++] = f; 203 } 204 205 qsort(fields, n, sizeof(fields[0]), field_compar); 206 207 fprintf(out, "%s %s{ ", 208 type->storage == STORAGE_STRUCT ? "struct" : "union", 209 type->struct_union.packed ? "@packed " : ""); 210 for (size_t i = 0; i < n; ++i) { 211 const struct struct_field *f = fields[i]; 212 if (!type->struct_union.c_compat) { 213 fprintf(out, "@offset(%zd) ", f->offset); 214 } 215 if (f->name) { 216 fprintf(out, "%s: ", f->name); 217 } 218 ret &= emit_type(f->type, out); 219 fprintf(out, ", "); 220 } 221 fprintf(out, "}"); 222 return ret; 223 } 224 225 bool 226 emit_type(const struct type *type, FILE *out) 227 { 228 bool ret = true; 229 if (type->flags & TYPE_CONST) { 230 fprintf(out, "const "); 231 } 232 if (type->flags & TYPE_ERROR) { 233 fprintf(out, "!"); 234 } 235 236 char *ident; 237 switch (type->storage) { 238 case STORAGE_BOOL: 239 case STORAGE_CHAR: 240 case STORAGE_ERROR: 241 case STORAGE_F32: 242 case STORAGE_F64: 243 case STORAGE_FCONST: 244 case STORAGE_I16: 245 case STORAGE_I32: 246 case STORAGE_I64: 247 case STORAGE_I8: 248 case STORAGE_INT: 249 case STORAGE_NULL: 250 case STORAGE_RCONST: 251 case STORAGE_RUNE: 252 case STORAGE_SIZE: 253 case STORAGE_STRING: 254 case STORAGE_U16: 255 case STORAGE_U32: 256 case STORAGE_U64: 257 case STORAGE_U8: 258 case STORAGE_UINT: 259 case STORAGE_UINTPTR: 260 case STORAGE_VALIST: 261 case STORAGE_VOID: 262 fprintf(out, "%s", type_storage_unparse(type->storage)); 263 break; 264 case STORAGE_POINTER: 265 fprintf(out, "%s*", type->pointer.flags & PTR_NULLABLE 266 ? "nullable " : ""); 267 ret &= emit_type(type->pointer.referent, out); 268 break; 269 case STORAGE_ARRAY: 270 if (type->array.length == SIZE_UNDEFINED) { 271 fprintf(out, "[*]"); 272 } else { 273 fprintf(out, "[%zd]", type->array.length); 274 } 275 ret &= emit_type(type->array.members, out); 276 break; 277 case STORAGE_SLICE: 278 fprintf(out, "[]"); 279 ret &= emit_type(type->array.members, out); 280 break; 281 case STORAGE_ALIAS: 282 ret &= type->alias.exported; 283 ident = identifier_unparse(&type->alias.ident); 284 fprintf(out, "%s", ident); 285 free(ident); 286 break; 287 case STORAGE_TAGGED: 288 fprintf(out, "("); 289 for (const struct type_tagged_union *tu = &type->tagged; 290 tu; tu = tu->next) { 291 ret &= emit_type(tu->type, out); 292 if (tu->next) { 293 fprintf(out, " | "); 294 } 295 } 296 fprintf(out, ")"); 297 break; 298 case STORAGE_STRUCT: 299 case STORAGE_UNION: 300 ret &= emit_struct(type, out); 301 break; 302 case STORAGE_FUNCTION: 303 if (type->func.flags & FN_NORETURN) { 304 fprintf(out, "@noreturn "); 305 } 306 fprintf(out, "fn("); 307 for (const struct type_func_param *param = type->func.params; 308 param; param = param->next) { 309 fprintf(out, "_: "); 310 if (param->next) { 311 ret &= emit_type(param->type, out); 312 fprintf(out, ", "); 313 } else if (type->func.variadism == VARIADISM_HARE) { 314 ret &= emit_type(param->type->array.members, out); 315 fprintf(out, "..."); 316 } else if (type->func.variadism == VARIADISM_C) { 317 ret &= emit_type(param->type, out); 318 fprintf(out, ", ..."); 319 } else { 320 ret &= emit_type(param->type, out); 321 } 322 } 323 fprintf(out, ") "); 324 ret &= emit_type(type->func.result, out); 325 break; 326 case STORAGE_ENUM: 327 ret &= type->alias.exported; 328 ident = identifier_unparse(&type->alias.ident); 329 fprintf(out, "%s", ident); 330 free(ident); 331 break; 332 case STORAGE_TUPLE: 333 fprintf(out, "("); 334 for (const struct type_tuple *tuple = &type->tuple; 335 tuple; tuple = tuple->next) { 336 ret &= emit_type(tuple->type, out); 337 if (tuple->next) { 338 fprintf(out, ", "); 339 } 340 } 341 fprintf(out, ")"); 342 break; 343 case STORAGE_ICONST: 344 fprintf(out, "[iconst min=%jd max=%jd]", type->_const.min, 345 type->_const.max); 346 break; 347 } 348 return ret; 349 } 350 351 static void 352 emit_exported_type(const struct type *type, FILE *out, const char *ident) 353 { 354 if (!emit_type(type, out)) { 355 // XXX: Hack 356 struct type *_type = (struct type *)type; 357 _type->alias.exported = true; 358 fprintf(stderr, "Cannot use unexported type "); 359 emit_type(type, stderr); 360 fprintf(stderr, " in exported declaration '%s'\n", ident); 361 exit(EXIT_FAILURE); 362 } 363 } 364 365 static void 366 emit_decl_const(struct declaration *decl, FILE *out) 367 { 368 char *ident = identifier_unparse(&decl->ident); 369 fprintf(out, "export def %s: ", ident); 370 if (decl->constant.type) { 371 emit_exported_type(decl->constant.type, out, ident); 372 } else { 373 emit_exported_type(decl->constant.value->result, out, ident); 374 }; 375 free(ident); 376 fprintf(out, " = "); 377 emit_const(decl->constant.value, out); 378 fprintf(out, ";\n"); 379 } 380 381 static void 382 emit_decl_func(struct declaration *decl, FILE *out) 383 { 384 char *ident = identifier_unparse(&decl->ident); 385 const struct type *fntype = decl->func.type; 386 fprintf(out, "export"); 387 if (decl->symbol) { 388 fprintf(out, " @symbol(\"%s\")", decl->symbol); 389 } 390 fprintf(out, "%s fn %s(", 391 (fntype->func.flags & FN_NORETURN) ? " @noreturn" : "", 392 ident); 393 394 for (struct type_func_param *param = fntype->func.params; 395 param; param = param->next) { 396 fprintf(out, "_: "); 397 if (param->next) { 398 emit_exported_type(param->type, out, ident); 399 fprintf(out, ", "); 400 } else if (fntype->func.variadism == VARIADISM_HARE) { 401 emit_exported_type(param->type->array.members, out, ident); 402 fprintf(out, "..."); 403 } else if (fntype->func.variadism == VARIADISM_C) { 404 emit_exported_type(param->type, out, ident); 405 fprintf(out, ", ..."); 406 } else { 407 emit_exported_type(param->type, out, ident); 408 } 409 } 410 411 fprintf(out, ") "); 412 emit_exported_type(fntype->func.result, out, ident); 413 fprintf(out, ";\n"); 414 free(ident); 415 } 416 417 static void 418 emit_decl_global(struct declaration *decl, FILE *out) 419 { 420 char *ident = identifier_unparse(&decl->ident); 421 fprintf(out, "export let "); 422 if (decl->symbol) { 423 fprintf(out, "@symbol(\"%s\") ", decl->symbol); 424 } 425 if (decl->global.threadlocal) { 426 fprintf(out, "@threadlocal "); 427 } 428 fprintf(out, "%s: ", ident); 429 if (decl->constant.type) { 430 emit_exported_type(decl->global.type, out, ident); 431 } else { 432 emit_exported_type(decl->global.value->result, out, ident); 433 }; 434 fprintf(out, ";\n"); 435 free(ident); 436 } 437 438 static void 439 emit_decl_type(struct declaration *decl, FILE *out) 440 { 441 char *ident = identifier_unparse(&decl->ident); 442 fprintf(out, "export type %s = ", ident); 443 assert(decl->_type->storage == STORAGE_ALIAS 444 || decl->_type->storage == STORAGE_ENUM); 445 if (decl->_type->storage == STORAGE_ENUM) { 446 const struct type *type = decl->_type; 447 fprintf(out, "enum %s { ", 448 type_storage_unparse(type->alias.type->storage)); 449 for (const struct scope_object *ev = type->_enum.values->objects; 450 ev; ev = ev->lnext) { 451 assert(ev->otype != O_SCAN); 452 fprintf(out, "%s = ", ev->name.name); 453 emit_const(ev->value, out); 454 fprintf(out, ", "); 455 } 456 fprintf(out, "}"); 457 } else { 458 emit_exported_type(decl->_type->alias.type, out, ident); 459 } 460 fprintf(out, "; // size: %zd, align: %zd, id: %u\n", 461 decl->_type->size, decl->_type->align, decl->_type->id); 462 free(ident); 463 } 464 465 void 466 emit_typedefs(struct unit *unit, FILE *out) 467 { 468 for (struct identifiers *imports = unit->imports; 469 imports; imports = imports->next) { 470 char *ident = identifier_unparse(&imports->ident); 471 fprintf(out, "use %s;\n", ident); 472 free(ident); 473 } 474 475 for (struct declarations *decls = unit->declarations; 476 decls; decls = decls->next) { 477 struct declaration *decl = decls->decl; 478 if (!decl->exported) { 479 continue; 480 } 481 482 switch (decl->type) { 483 case DECL_CONST: 484 emit_decl_const(decl, out); 485 break; 486 case DECL_FUNC: 487 emit_decl_func(decl, out); 488 break; 489 case DECL_GLOBAL: 490 emit_decl_global(decl, out); 491 break; 492 case DECL_TYPE: 493 emit_decl_type(decl, out); 494 break; 495 } 496 } 497 }