Cthulhu  0.2.10
Cthulhu compiler collection
type.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "base/util.h"
4 #include "common.h"
5 
6 #include "cthulhu/tree/query.h"
7 
8 #include "std/map.h"
9 #include "std/vector.h"
10 #include "std/typed/vector.h"
11 
12 #include "arena/arena.h"
13 #include "memory/memory.h"
14 #include "base/panic.h"
15 #include <stdio.h>
16 
17 ssa_type_t *ssa_type_new(ssa_kind_t kind, const char *name, tree_quals_t quals)
18 {
19  arena_t *arena = get_global_arena();
20  ssa_type_t *type = ARENA_MALLOC(sizeof(ssa_type_t), name, NULL, arena);
21  type->kind = kind;
22  type->quals = quals;
23  type->name = name;
24  return type;
25 }
26 
27 ssa_type_t *ssa_type_empty(const char *name, tree_quals_t quals)
28 {
29  return ssa_type_new(eTypeEmpty, name, quals);
30 }
31 
32 ssa_type_t *ssa_type_unit(const char *name, tree_quals_t quals)
33 {
34  return ssa_type_new(eTypeUnit, name, quals);
35 }
36 
37 ssa_type_t *ssa_type_bool(const char *name, tree_quals_t quals)
38 {
39  return ssa_type_new(eTypeBool, name, quals);
40 }
41 
42 ssa_type_t *ssa_type_digit(const char *name, tree_quals_t quals, sign_t sign, digit_t digit)
43 {
44  ssa_type_digit_t it = { .sign = sign, .digit = digit };
45  ssa_type_t *type = ssa_type_new(eTypeDigit, name, quals);
46  type->digit = it;
47  return type;
48 }
49 
50 ssa_type_t *ssa_type_closure(const char *name, tree_quals_t quals, ssa_type_t *result, typevec_t *params, bool variadic)
51 {
52  ssa_type_closure_t it = {
53  .result = result,
54  .params = params,
55  .variadic = variadic
56  };
57 
58  ssa_type_t *closure = ssa_type_new(eTypeClosure, name, quals);
59  closure->closure = it;
60  return closure;
61 }
62 
63 ssa_type_t *ssa_type_pointer(const char *name, tree_quals_t quals, ssa_type_t *pointer, size_t length)
64 {
65  ssa_type_pointer_t it = {
66  .pointer = pointer,
67  .length = length
68  };
69 
70  ssa_type_t *ptr = ssa_type_new(eTypePointer, name, quals);
71  ptr->pointer = it;
72  return ptr;
73 }
74 
76 {
77  return ssa_type_new(eTypeOpaque, name, quals);
78 }
79 
80 ssa_type_t *ssa_type_struct(const char *name, tree_quals_t quals, typevec_t *fields)
81 {
82  ssa_type_record_t it = { .fields = fields };
83  ssa_type_t *type = ssa_type_new(eTypeStruct, name, quals);
84  type->record = it;
85  return type;
86 }
87 
88 ssa_type_t *ssa_type_union(const char *name, tree_quals_t quals, typevec_t *fields)
89 {
90  ssa_type_record_t it = { .fields = fields };
91  ssa_type_t *type = ssa_type_new(eTypeUnion, name, quals);
92  type->record = it;
93  return type;
94 }
95 
96 ssa_type_t *ssa_type_enum(const char *name, tree_quals_t quals, ssa_type_t *underlying, typevec_t *cases)
97 {
98  CTASSERTF(underlying->kind == eTypeDigit, "expected digit, got %d", underlying->kind);
99 
100  ssa_type_enum_t it = { .underlying = underlying, .cases = cases };
101  ssa_type_t *type = ssa_type_new(eTypeEnum, name, quals);
102  type->sum = it;
103  return type;
104 }
105 
106 static typevec_t *collect_cases(const tree_t *type, arena_t *arena)
107 {
108  CTASSERTF(tree_is(type, eTreeTypeEnum), "expected enum, got %s", tree_to_string(type));
109 
110  vector_t *vec = tree_enum_get_cases(type);
111  size_t len = vector_len(vec);
112 
113  typevec_t *result = typevec_of(sizeof(ssa_case_t), len, arena);
114 
115  for (size_t i = 0; i < len; i++)
116  {
117  const tree_t *it = vector_get(vec, i);
118  CTASSERTF(tree_is(it, eTreeDeclCase), "expected case, got %s", tree_to_string(it));
119 
120  const char *name = tree_get_name(it);
121  const tree_t *expr = it->case_value;
122 
123  // TODO: eval case_value
124  CTASSERTF(tree_is(expr, eTreeExprDigit), "only digit literal case values are supported, got %s", tree_to_string(expr));
125 
126  ssa_case_t entry = {
127  .name = name,
128  };
129  mpz_init_set(entry.value, expr->digit_value);
130 
131  typevec_set(result, i, &entry);
132  }
133 
134  return result;
135 }
136 
137 static typevec_t *collect_params(map_t *cache, const tree_t *type, arena_t *arena)
138 {
139  const vector_t *vec = tree_fn_get_params(type);
140 
141  size_t len = vector_len(vec);
142  typevec_t *result = typevec_of(sizeof(ssa_param_t), len, arena);
143 
144  for (size_t i = 0; i < len; i++)
145  {
146  const tree_t *param = vector_get(vec, i);
147  CTASSERTF(tree_is(param, eTreeDeclParam), "expected param, got %s", tree_to_string(param));
148 
149  const char *name = tree_get_name(param);
150  const tree_t *param_type = tree_get_type(param);
151 
152  ssa_param_t entry = {
153  .name = name,
154  .type = ssa_type_create_cached(cache, param_type)
155  };
156 
157  typevec_set(result, i, &entry);
158  }
159 
160  return result;
161 }
162 
163 static typevec_t *collect_fields(map_t *cache, const tree_t *type, arena_t *arena)
164 {
165  size_t len = vector_len(type->fields);
166  typevec_t *result = typevec_of(sizeof(ssa_field_t), len, arena);
167  for (size_t i = 0; i < len; i++)
168  {
169  const tree_t *field = vector_get(type->fields, i);
170  CTASSERTF(tree_is(field, eTreeDeclField), "expected field, got %s", tree_to_string(field));
171 
172  const char *name = tree_get_name(field);
173  const tree_t *field_type = tree_get_type(field);
174 
175  ssa_field_t entry = {
176  .name = name,
177  .type = ssa_type_create_cached(cache, field_type)
178  };
179 
180  typevec_set(result, i, &entry);
181  }
182 
183  return result;
184 }
185 
186 static ssa_type_t *ssa_type_create(map_t *cache, const tree_t *type, arena_t *arena)
187 {
188  tree_kind_t kind = tree_get_kind(type);
189  const char *name = tree_get_name(type);
190  tree_quals_t quals = tree_ty_get_quals(type);
191 
192  switch (kind)
193  {
194  case eTreeTypeAlias: return ssa_type_create(cache, tree_get_type(type), arena);
195  case eTreeTypeEmpty: return ssa_type_empty(name, quals);
196  case eTreeTypeUnit: return ssa_type_unit(name, quals);
197  case eTreeTypeBool: return ssa_type_bool(name, quals);
198  case eTreeTypeDigit: return ssa_type_digit(name, quals, type->sign, type->digit);
199  case eTreeTypeClosure:
200  return ssa_type_closure(
201  /* name = */ name,
202  /* quals = */ quals,
203  /* result = */ ssa_type_create_cached(cache, tree_fn_get_return(type)),
204  /* params = */ collect_params(cache, type, arena),
205  /* variadic = */ tree_fn_get_arity(type) == eArityVariable
206  );
207 
208  case eTreeTypeReference:
209  return ssa_type_pointer(name, quals, ssa_type_create_cached(cache, type->ptr), 1);
210 
211  case eTreeTypeArray:
212  case eTreeTypePointer:
213  return ssa_type_pointer(name, quals, ssa_type_create_cached(cache, type->ptr), type->length);
214 
215  case eTreeTypeOpaque:
216  return ssa_type_opaque_pointer(name, quals);
217 
218  case eTreeTypeEnum: return ssa_type_enum(name, quals, ssa_type_create_cached(cache, type->underlying), collect_cases(type, arena));
219  case eTreeTypeStruct: return ssa_type_struct(name, quals, collect_fields(cache, type, arena));
220  case eTreeTypeUnion: return ssa_type_union(name, quals, collect_fields(cache, type, arena));
221 
222  default: CT_NEVER("unexpected type kind: %s", tree_to_string(type));
223  }
224 }
225 
227 {
228  ssa_type_t *old = map_get(cache, type);
229  if (old != NULL) { return old; }
230 
231  ssa_type_t *temp = ssa_type_empty(tree_get_name(type), eQualNone);
232  map_set(cache, type, temp);
233 
234  arena_t *arena = get_global_arena();
235 
236  ssa_type_t *result = ssa_type_create(cache, type, arena);
237  ctu_memcpy(temp, result, sizeof(ssa_type_t));
238  return temp;
239 }
CT_PUREFN CT_TREE_API tree_kind_t tree_get_kind(const tree_t *tree)
Definition: context.c:143
CT_PUREFN CT_TREE_API const char * tree_get_name(const tree_t *tree)
Definition: context.c:102
CT_PUREFN CT_TREE_API const tree_t * tree_get_type(const tree_t *tree)
Definition: context.c:132
CT_PUREFN CT_TREE_API bool tree_is(const tree_t *self, tree_kind_t kind)
Definition: query.c:91
ssa_type_t * ssa_type_create_cached(map_t *cache, const tree_t *type)
Definition: type.c:226
ssa_type_t * ssa_type_union(const char *name, tree_quals_t quals, typevec_t *fields)
Definition: type.c:88
ssa_type_t * ssa_type_new(ssa_kind_t kind, const char *name, tree_quals_t quals)
Definition: type.c:17
ssa_type_t * ssa_type_empty(const char *name, tree_quals_t quals)
Definition: type.c:27
ssa_type_t * ssa_type_opaque_pointer(const char *name, tree_quals_t quals)
Definition: type.c:75
ssa_type_t * ssa_type_unit(const char *name, tree_quals_t quals)
Definition: type.c:32
ssa_type_t * ssa_type_enum(const char *name, tree_quals_t quals, ssa_type_t *underlying, typevec_t *cases)
Definition: type.c:96
ssa_type_t * ssa_type_struct(const char *name, tree_quals_t quals, typevec_t *fields)
Definition: type.c:80
ssa_type_t * ssa_type_closure(const char *name, tree_quals_t quals, ssa_type_t *result, typevec_t *params, bool variadic)
Definition: type.c:50
CT_PUREFN CT_TREE_API tree_arity_t tree_fn_get_arity(const tree_t *self)
Definition: query.c:191
CT_TREE_API const char * tree_to_string(const tree_t *self)
Definition: query.c:40
CT_PUREFN CT_TREE_API const tree_t * tree_fn_get_return(const tree_t *self)
Definition: query.c:167
CT_PUREFN CT_TREE_API tree_quals_t tree_ty_get_quals(const tree_t *self)
Definition: query.c:257
CT_PUREFN CT_TREE_API vector_t * tree_enum_get_cases(const tree_t *self)
Definition: query.c:156
CT_PUREFN CT_TREE_API const vector_t * tree_fn_get_params(const tree_t *self)
Definition: query.c:179
CT_NOALIAS CT_BASE_API void * ctu_memcpy(STA_WRITES(size) void *CT_RESTRICT dst, STA_READS(size) const void *CT_RESTRICT src, size_t size)
copy memory from one location to another equivalent to memcpy but with safety checks
CT_MEMORY_API arena_t * get_global_arena(void)
get the global memory arena
Definition: memory.c:16
CT_STD_API void map_set(map_t *map, const void *key, void *value)
set a key-value pair in a map
Definition: map.c:294
CT_NODISCARD CT_PUREFN CT_STD_API void * map_get(const map_t *map, const void *key)
get a value from a map
Definition: map.c:324
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
#define CT_NEVER(...)
assert that a code path is never reached
Definition: panic.h:136
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
ssa_kind_t
Definition: ssa.h:40
ssa_type_t * ssa_type_bool(const char *name, tree_quals_t quals)
Definition: type.c:37
ssa_type_t * ssa_type_pointer(const char *name, tree_quals_t quals, ssa_type_t *pointer, size_t length)
Definition: type.c:63
ssa_type_t * ssa_type_digit(const char *name, tree_quals_t quals, sign_t sign, digit_t digit)
Definition: type.c:42
tree_quals_t
all type qualifiers
Definition: ops.h:25
sign_t
integer sign
Definition: ops.h:104
tree_kind_t
all tree node types
Definition: ops.h:17
digit_t
digit width
Definition: ops.h:96
CT_STD_API void typevec_set(typevec_t *vec, size_t index, const void *src)
set an element in the vector
Definition: vector.c:128
CT_NODISCARD CT_STD_API typevec_t * typevec_of(size_t width, size_t len, arena_t *arena)
create a new typed vector with an initial size and length
Definition: vector.c:83
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
Definition: vector.c:134
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
Definition: vector.c:152
an allocator object
Definition: arena.h:86
an unordered hash map
Definition: map.h:38
mpz_t value
Definition: ssa.h:122
const char * name
Definition: ssa.h:121
const char * name
Definition: ssa.h:107
const char * name
Definition: ssa.h:90
const ssa_type_t * result
Definition: ssa.h:131
sign_t sign
Definition: ssa.h:116
ssa_type_t * underlying
Definition: ssa.h:126
const ssa_type_t * pointer
Definition: ssa.h:137
typevec_t * fields
Definition: ssa.h:142
ssa_kind_t kind
Definition: ssa.h:146
tree_quals_t quals
Definition: ssa.h:147
ssa_type_record_t record
Definition: ssa.h:154
ssa_type_closure_t closure
Definition: ssa.h:152
ssa_type_digit_t digit
Definition: ssa.h:151
ssa_type_enum_t sum
Definition: ssa.h:155
const char * name
Definition: ssa.h:148
ssa_type_pointer_t pointer
Definition: ssa.h:153
Definition: tree.h:67
sign_t sign
Definition: tree.h:180
const tree_t * underlying
Definition: tree.h:188
vector_t * fields
Definition: tree.h:184
size_t length
Definition: tree.h:174
const tree_t * ptr
Definition: tree.h:172
mpz_t digit_value
Definition: tree.h:75
digit_t digit
Definition: tree.h:179
tree_t * case_value
Definition: tree.h:194
A vector with a fixed type size.
Definition: vector.h:24
a generic vector of pointers
Definition: vector.c:16