aboutsummaryrefslogtreecommitdiff
path: root/type.c
diff options
context:
space:
mode:
Diffstat (limited to 'type.c')
-rw-r--r--type.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/type.c b/type.c
new file mode 100644
index 0000000..6dd4dd0
--- /dev/null
+++ b/type.c
@@ -0,0 +1,79 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#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);
+ }
+}