Cthulhu  0.2.10
Cthulhu compiler collection
common.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "common.h"
4 
5 #include "std/str.h"
6 #include "std/map.h"
7 #include "std/vector.h"
8 #include "std/typed/vector.h"
9 
10 #include "fs/fs.h"
11 
12 #include "base/panic.h"
13 
14 #include <stdarg.h>
15 #include <stdint.h>
16 
17 char *begin_module(emit_t *emit, fs_t *fs, const ssa_module_t *mod)
18 {
19  // if the last element of the path and the module name are the same then remove the last element
20  // this isnt required to be semanticly correct but it makes the output look nicer
21 
22  char *path = str_replace(mod->name, ".", "/", emit->arena);
23 
24  // create a folder if we need one for this module
25  if (str_contains(mod->name, "."))
26  {
27  fs_dir_create(fs, path);
28  }
29 
30  return path;
31 }
32 
33 static void names_reset(names_t *names)
34 {
35  map_reset(names->names);
36  names->counter = 0;
37 }
38 
39 names_t names_new(size_t size, arena_t *arena)
40 {
41  names_t names = {
42  .counter = 0,
43  .names = map_optimal(size, kTypeInfoPtr, arena)
44  };
45 
46  return names;
47 }
48 
49 void counter_reset(emit_t *emit)
50 {
51  names_reset(&emit->vreg_names);
52  names_reset(&emit->block_names);
53 }
54 
55 static char *name_increment(names_t *names, const void *obj, char *existing, arena_t *arena)
56 {
57  char *name = map_get(names->names, obj);
58  if (name != NULL) { return name; }
59 
60  if (existing != NULL)
61  {
62  map_set(names->names, obj, existing);
63  return existing;
64  }
65 
66  char *id = str_format(arena, "%zu", names->counter++);
67  map_set(names->names, obj, id);
68  return id;
69 }
70 
71 char *get_step_name(emit_t *emit, const ssa_step_t *step)
72 {
73  return name_increment(&emit->vreg_names, step, NULL, emit->arena);
74 }
75 
76 char *get_block_name(emit_t *emit, const ssa_block_t *block)
77 {
78  return name_increment(&emit->block_names, block, (char*)block->name, emit->arena);
79 }
80 
81 char *get_step_from_block(emit_t *emit, const ssa_block_t *block, size_t index)
82 {
83  ssa_step_t *step = typevec_offset(block->steps, index);
84  return get_step_name(emit, step);
85 }
86 
87 static char *digit_to_string(ssa_type_digit_t digit, arena_t *arena)
88 {
89  return str_format(arena, "digit(%s.%s)", sign_name(digit.sign), digit_name(digit.digit));
90 }
91 
92 static char *params_to_string(typevec_t *params, arena_t *arena)
93 {
94  size_t len = typevec_len(params);
95  vector_t *vec = vector_of(len, arena);
96  for (size_t i = 0; i < len; i++)
97  {
98  const ssa_param_t *param = typevec_offset(params, i);
99  const char *ty = type_to_string(param->type, arena);
100  vector_set(vec, i, str_format(arena, "%s: %s", param->name, ty));
101  }
102 
103  return str_join(", ", vec, arena);
104 }
105 
106 static char *closure_to_string(ssa_type_closure_t closure, arena_t *arena)
107 {
108  const char *result = type_to_string(closure.result, arena);
109  char *params = params_to_string(closure.params, arena);
110 
111  return str_format(arena, "closure(result: %s, params: [%s], variadic: %s)", result, params, closure.variadic ? "true" : "false");
112 }
113 
114 static char *pointer_to_string(ssa_type_pointer_t pointer, arena_t *arena)
115 {
116  const char *pointee = type_to_string(pointer.pointer, arena);
117  switch (pointer.length)
118  {
119  case 0: return str_format(arena, "ptr(%s)", pointee);
120  case SIZE_MAX: return str_format(arena, "unbounded-ptr(%s)", pointee);
121  default: return str_format(arena, "ptr(%s of %zu)", pointee, pointer.length);
122  }
123 }
124 
125 static char *record_to_string(ssa_type_record_t record, arena_t *arena)
126 {
127  size_t len = typevec_len(record.fields);
128  vector_t *fields = vector_of(len, arena);
129  for (size_t i = 0; i < len; i++)
130  {
131  const ssa_field_t *field = typevec_offset(record.fields, i);
132  vector_set(fields, i, (char*)field->name);
133  }
134 
135  char *joined = str_join(", ", fields, arena);
136  return str_format(arena, "record(fields: [%s])", joined);
137 }
138 
139 static char *enum_to_string(ssa_type_enum_t sum, arena_t *arena)
140 {
141  size_t len = typevec_len(sum.cases);
142  vector_t *variants = vector_of(len, arena);
143  for (size_t i = 0; i < len; i++)
144  {
145  const ssa_case_t *field = typevec_offset(sum.cases, i);
146  char *segment = str_format(arena, "%s: %s", field->name, mpz_get_str(NULL, 10, field->value));
147  vector_set(variants, i, segment);
148  }
149 
150  char *joined = str_join(", ", variants, arena);
151  return str_format(arena, "enum(variants: [%s])", joined);
152 }
153 
154 const char *type_to_string(const ssa_type_t *type, arena_t *arena)
155 {
156  switch (type->kind)
157  {
158  case eTypeEmpty: return "empty";
159  case eTypeUnit: return "unit";
160  case eTypeBool: return "bool";
161  case eTypeOpaque: return "opaque";
162  case eTypeEnum: return enum_to_string(type->sum, arena);
163  case eTypeDigit: return digit_to_string(type->digit, arena);
164  case eTypeClosure: return closure_to_string(type->closure, arena);
165  case eTypePointer: return pointer_to_string(type->pointer, arena);
166  case eTypeStruct: return record_to_string(type->record, arena);
167  default: CT_NEVER("unknown type kind %d", type->kind);
168  }
169 }
CT_NODISCARD size_t size
Definition: scan.h:128
CT_FS_API os_error_t fs_dir_create(fs_t *fs, const char *path)
create a directory create a directory and all child directories inside a filesystem
Definition: fs.c:333
CT_NODISCARD CT_STD_API map_t * map_optimal(size_t size, hash_info_t info, arena_t *arena)
create a new map with an optimal size
Definition: optimal.c:85
CT_STD_API void map_reset(map_t *map)
clear all key-value pairs from a map
Definition: map.c:386
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 CT_NEVER(...)
assert that a code path is never reached
Definition: panic.h:136
CT_NODISCARD CT_STD_API char * str_replace(const char *str, const char *search, const char *repl, arena_t *arena)
replace all instances of a substring in a string
Definition: str.c:616
CT_NODISCARD CT_STD_API char * str_join(const char *sep, const vector_t *parts, arena_t *arena)
join strings
Definition: str.c:274
CT_NODISCARD CT_PUREFN CT_STD_API bool str_contains(const char *str, const char *search)
check if a string contains a substring
Definition: str.c:607
CT_TREE_API const char * sign_name(sign_t sign)
get the pretty name of a integer sign
Definition: ops.c:90
CT_TREE_API const char * digit_name(digit_t digit)
get the pretty name of a digit
Definition: ops.c:102
CT_STD_API const hash_info_t kTypeInfoPtr
type information for a generic pointer this operates on the pointer itself and not the data it points...
Definition: typeinfo.c:41
CT_NODISCARD CT_PUREFN CT_STD_API size_t typevec_len(const typevec_t *vec)
get the length of a vector
Definition: vector.c:120
CT_NODISCARD CT_PUREFN CT_STD_API void * typevec_offset(const typevec_t *vec, size_t index)
get a pointer to the value at the given index
Definition: vector.c:191
CT_NODISCARD CT_STD_API vector_t * vector_of(size_t len, arena_t *arena)
create a new vector with a specified length
Definition: vector.c:71
CT_STD_API void vector_set(vector_t *vector, size_t index, void *value)
set a value in a vector
Definition: vector.c:125
STA_DECL char * str_format(arena_t *arena, const char *fmt,...)
Definition: str.c:97
an allocator object
Definition: arena.h:86
target code emitter options
Definition: common.h:16
arena_t * arena
arena to use
Definition: common.h:17
names_t block_names
Definition: common.h:20
names_t vreg_names
Definition: common.h:21
Definition: common.h:72
Definition: common.h:10
map_t * names
Definition: common.h:12
size_t counter
Definition: common.h:11
typevec_t * steps
Definition: ssa.h:330
const char * name
Definition: ssa.h:329
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:355
const char * name
Definition: ssa.h:90
const ssa_type_t * type
Definition: ssa.h:91
const ssa_type_t * result
Definition: ssa.h:131
bool variadic
Definition: ssa.h:133
typevec_t * params
Definition: ssa.h:132
digit_t digit
Definition: ssa.h:117
sign_t sign
Definition: ssa.h:116
typevec_t * cases
Definition: ssa.h:127
const ssa_type_t * pointer
Definition: ssa.h:137
size_t length
Definition: ssa.h:138
typevec_t * fields
Definition: ssa.h:142
ssa_kind_t kind
Definition: ssa.h:146
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
ssa_type_pointer_t pointer
Definition: ssa.h:153
A vector with a fixed type size.
Definition: vector.h:24
a generic vector of pointers
Definition: vector.c:16
void counter_reset(emit_t *emit)
Definition: common.c:49
names_t names_new(size_t size, arena_t *arena)
Definition: common.c:39
char * begin_module(emit_t *emit, fs_t *fs, const ssa_module_t *mod)
Definition: common.c:17
char * get_step_name(emit_t *emit, const ssa_step_t *step)
Definition: common.c:72
char * get_block_name(emit_t *emit, const ssa_block_t *block)
Definition: common.c:77
char * get_step_from_block(emit_t *emit, const ssa_block_t *block, size_t index)
Definition: common.c:103
const char * type_to_string(const ssa_type_t *type, arena_t *arena)
Definition: common.c:176