libscript_internal.h (5302B)
1 #ifndef LIBSCRIPT_INTERNAL_H 2 #define LIBSCRIPT_INTERNAL_H 3 4 #include "libscript.h" 5 6 #include <ctype.h> 7 #include <inttypes.h> 8 #include <limits.h> 9 10 #define UNREACHABLE() (*((volatile char *) 0) = 0) 11 #define PANIC() UNREACHABLE() 12 13 /* utilities 14 * =========================================================================== 15 */ 16 17 #define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) 18 #define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align)) 19 20 struct arena { 21 void *ptr; 22 size_t cap, len; 23 }; 24 25 static inline void 26 arena_reset(struct arena *arena) 27 { 28 arena->len = 0; 29 } 30 31 static inline void * 32 arena_alloc(struct arena *arena, size_t size, size_t align) 33 { 34 size_t aligned_len = ALIGN_NEXT(arena->len, align); 35 if (aligned_len + size > arena->cap) 36 return NULL; 37 38 void *ptr = (void *) ((uintptr_t) arena->ptr + aligned_len); 39 arena->len = aligned_len + size; 40 41 return ptr; 42 } 43 44 #define ALLOC_ARRAY(arena, T, n) \ 45 arena_alloc((arena), sizeof(T) * (n), alignof(T)) 46 47 #define ALLOC_SIZED(arena, T) ALLOC_ARRAY((arena), T, 1) 48 49 static inline void 50 list_push_head(struct script_list *restrict list, 51 struct script_list_node *restrict node) 52 { 53 if (!list->tail) 54 list->tail = node; 55 56 if (list->head) 57 list->head->prev = node; 58 59 node->next = list->head; 60 list->head = node; 61 } 62 63 static inline void 64 list_push_tail(struct script_list *restrict list, 65 struct script_list_node *restrict node) 66 { 67 if (!list->head) 68 list->head = node; 69 70 if (list->tail) 71 list->tail->next = node; 72 73 node->prev = list->tail; 74 list->tail = node; 75 } 76 77 static inline struct script_list_node * 78 list_pop_head(struct script_list *list) 79 { 80 if (!list->head) 81 return NULL; 82 83 struct script_list_node *node = list->head; 84 list->head = node->next; 85 return node; 86 } 87 88 static inline struct script_list_node * 89 list_pop_tail(struct script_list *list) 90 { 91 if (!list->tail) 92 return NULL; 93 94 struct script_list_node *node = list->tail; 95 list->tail = node->prev; 96 return node; 97 } 98 99 struct identifier { 100 char *ptr; 101 size_t len; 102 }; 103 104 struct ident_pool { 105 struct identifier *ptr; 106 size_t cap, len; 107 }; 108 109 static inline struct script_flystr 110 ident_pool_intern(struct ident_pool *pool, char *str, size_t len) 111 { 112 /* TODO: switch to a hash table, or anything better than linear search */ 113 size_t i; 114 for (i = 0; i < pool->len; i++) { 115 struct identifier *ident = &pool->ptr[i]; 116 117 if (ident->len == len && strncmp(ident->ptr, str, len) == 0) 118 return (struct script_flystr) { .v = i, }; 119 } 120 121 assert(i < pool->cap); 122 123 pool->ptr[i].ptr = str; 124 pool->ptr[i].len = len; 125 pool->len++; 126 127 return (struct script_flystr) { .v = i, }; 128 } 129 130 static inline void 131 ident_pool_get(struct ident_pool *pool, struct script_flystr ident, char **str, size_t *len) 132 { 133 struct identifier *identifier = &pool->ptr[ident.v]; 134 135 *str = identifier->ptr; 136 *len = identifier->len; 137 } 138 139 struct token_stream { 140 struct script_token *ptr; 141 size_t cap, len, cur; 142 }; 143 144 static inline struct script_token * 145 token_stream_alloc(struct token_stream *stream) 146 { 147 if (stream->len >= stream->cap) 148 return NULL; 149 150 return &stream->ptr[stream->len++]; 151 } 152 153 struct symbol_table { 154 struct script_symbol *ptr; 155 size_t cap, len; 156 157 uintptr_t address; 158 }; 159 160 static inline struct script_symbol * 161 symbol_table_push(struct symbol_table *symtab) 162 { 163 if (symtab->len >= symtab->cap) 164 return NULL; 165 166 return &symtab->ptr[symtab->len++]; 167 } 168 169 static inline struct script_symbol * 170 symbol_table_push_scope(struct symbol_table *symtab) 171 { 172 return symbol_table_push(symtab); 173 } 174 175 static inline void 176 symbol_table_pop_scope(struct symbol_table *symtab, struct script_symbol *scope) 177 { 178 symtab->len = scope - symtab->ptr; 179 } 180 181 static inline struct script_symbol * 182 symbol_table_find(struct symbol_table *symtab, struct script_flystr ident) 183 { 184 for (size_t i = 1; i <= symtab->len; i++) { 185 struct script_symbol *sym = &symtab->ptr[symtab->len - i]; 186 if (sym->ident.v == ident.v) return sym; 187 } 188 189 return NULL; 190 } 191 192 static inline uintptr_t 193 symbol_table_next_addr(struct symbol_table *symtab, 194 struct script_typeinfo const *typeinfo) 195 { 196 uintptr_t addr = ALIGN_NEXT(symtab->address, typeinfo->alignment); 197 symtab->address = addr + typeinfo->size; 198 return addr; 199 } 200 201 struct ast { 202 struct script_list roots; 203 }; 204 205 struct ir { 206 struct script_ir_inst *ptr; 207 size_t cap, len; 208 }; 209 210 static inline struct script_ir_inst const * 211 ir_current_inst(struct ir *ir) 212 { 213 return &ir->ptr[ir->len]; 214 } 215 216 static inline struct script_ir_inst * 217 ir_push(struct ir *ir, struct script_ir_inst *inst) 218 { 219 if (ir->len >= ir->cap) 220 return NULL; 221 222 struct script_ir_inst *instruction = &ir->ptr[ir->len++]; 223 *instruction = *inst; 224 225 return instruction; 226 } 227 228 struct compile_ctx { 229 struct arena arena; 230 struct arena scratch; 231 232 FILE *errstream; 233 int verbose; 234 char *src; 235 size_t len; 236 237 struct ident_pool ident_pool; 238 239 struct token_stream stream; 240 241 struct symbol_table symtab; 242 243 struct ast ast; 244 245 struct ir ir; 246 }; 247 248 static inline void 249 dbglog(struct compile_ctx *ctx, char const *fmt, ...) 250 { 251 va_list va; 252 va_start(va, fmt); 253 vfprintf(ctx->errstream, fmt, va); 254 va_end(va); 255 } 256 257 static int 258 dump_token(struct script_token *token, char *buf, size_t cap); 259 260 static void 261 dump_token_stream(struct compile_ctx *ctx); 262 263 static void 264 dump_symbol_table(struct compile_ctx *ctx); 265 266 static void 267 dump_ast(struct compile_ctx *ctx); 268 269 static void 270 dump_ir(struct compile_ctx *ctx); 271 272 #endif /* LIBSCRIPT_INTERNAL_H */