#include #include #include #include "type.h" static struct { int cap, num; struct type **types; } cache; static struct type *voidtype; static void init_cache(void) { if (voidtype) return; voidtype = malloc(sizeof(struct type)); voidtype->tag = T_VOID; cache.cap = 8; cache.num = 0; cache.types = malloc(cache.cap * sizeof(struct type*)); } void type_cache_cleanup(void) { for (int i = 0; i < cache.num; i++) { free(cache.types[i]); } free(cache.types); free(voidtype); } static void cache_add(struct type *type) { if (cache.num == cache.cap) { cache.cap *= 2; cache.types = realloc(cache.types, cache.cap * sizeof(struct type*)); } cache.types[cache.num++] = type; } struct type* type_int(int size) { init_cache(); for (int i = 0; i < cache.num; i++) { if (cache.types[i]->tag == T_INT && cache.types[i]->size == size) { return cache.types[i]; } } struct type *type = malloc(sizeof(struct type)); type->tag = T_INT; type->size = size; cache_add(type); return type; } struct type* type_void(void) { return voidtype; } struct type* type_ptr(struct type *target) { init_cache(); for (int i = 0; i < cache.num; i++) { if (cache.types[i]->tag == T_PTR && cache.types[i]->target == target) { return cache.types[i]; } } struct type *type = malloc(sizeof(struct type)); type->tag = T_PTR; type->target = target; cache_add(type); return type; } void type_print(struct type *type, FILE *f) { switch (type->tag) { case T_INT: fprintf(f, "i%d", type->size); break; case T_VOID: fprintf(f, "void"); break; case T_PTR: type_print(type->target, f); fprintf(f, "*"); break; default: assert(false); } }