blob: 6dd4dd01a9e9b6526bd872c3cf55af759bc849c7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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);
}
}
|