#include "gen/gen.h" #include #include "bytecode.h" static void put(struct l2_generator *gen, unsigned char ch) { l2_bufio_put(&gen->writer, ch); gen->pos += 1; } static void put_u4le(struct l2_generator *gen, l2_word word) { char data[4] = { (word >> 0) & 0xff, (word >> 8) & 0xff, (word >> 16) & 0xff, (word >> 24) & 0xff, }; l2_bufio_put_n(&gen->writer, data, 4); gen->pos += 4; } static void put_d8le(struct l2_generator *gen, double num) { uint64_t integer; memcpy(&integer, &num, 8); char data[8] = { (integer >> 0) & 0xff, (integer >> 8) & 0xff, (integer >> 16) & 0xff, (integer >> 24) & 0xff, (integer >> 32) & 0xff, (integer >> 40) & 0xff, (integer >> 48) & 0xff, (integer >> 56) & 0xff, }; l2_bufio_put_n(&gen->writer, data, 8); gen->pos += 8; } void l2_gen_init(struct l2_generator *gen, struct l2_io_writer *w) { l2_strset_init(&gen->atomset); l2_strset_init(&gen->stringset); gen->strings = NULL; gen->pos = 0; l2_bufio_writer_init(&gen->writer, w); // Register atoms for all builtins #define Y(name, k) \ l2_strset_put_copy(&gen->atomset, name); #define X(name, f) \ l2_strset_put_copy(&gen->atomset, name); #include "builtins.x.h" #undef Y #undef X } void l2_gen_flush(struct l2_generator *gen) { l2_bufio_flush(&gen->writer); } void l2_gen_free(struct l2_generator *gen) { l2_strset_free(&gen->atomset); l2_strset_free(&gen->stringset); free(gen->strings); } void l2_gen_halt(struct l2_generator *gen) { put(gen, L2_OP_HALT); } void l2_gen_rjmp(struct l2_generator *gen, l2_word len) { put(gen, L2_OP_RJMP_U4); put_u4le(gen, len); } void l2_gen_discard(struct l2_generator *gen) { put(gen, L2_OP_DISCARD); } void l2_gen_swap_discard(struct l2_generator *gen) { put(gen, L2_OP_SWAP_DISCARD); } void l2_gen_ret(struct l2_generator *gen) { put(gen, L2_OP_RET); } void l2_gen_none(struct l2_generator *gen) { put(gen, L2_OP_ALLOC_NONE); } void l2_gen_number(struct l2_generator *gen, double num) { uint64_t n; memcpy(&n, &num, sizeof(num)); put(gen, L2_OP_ALLOC_REAL_D8); put_d8le(gen, num); } void l2_gen_atom(struct l2_generator *gen, char **str) { size_t id = l2_strset_put(&gen->atomset, str); put(gen, L2_OP_ALLOC_ATOM_U4); put_u4le(gen, id); } void l2_gen_atom_copy(struct l2_generator *gen, char *str) { size_t id = l2_strset_put_copy(&gen->atomset, str); put(gen, L2_OP_ALLOC_ATOM_U4); put_u4le(gen, id); } void l2_gen_string(struct l2_generator *gen, char **str) { size_t id = l2_strset_get(&gen->stringset, *str); if (id == 0) { size_t len = strlen(*str); size_t aligned = len; if (aligned % sizeof(l2_word) != 0) { aligned += sizeof(l2_word) - (aligned % sizeof(l2_word)); } put(gen, L2_OP_RJMP_U4); put_u4le(gen, aligned / sizeof(l2_word)); l2_word pos = gen->pos; gen->pos += aligned / sizeof(l2_word); l2_bufio_put_n(&gen->writer, *str, len); for (size_t i = len; i < aligned; ++i) { l2_bufio_put(&gen->writer, '\0'); } id = l2_strset_put(&gen->stringset, str); gen->strings = realloc(gen->strings, id * sizeof(*gen->strings)); gen->strings[id - 1].length = len; gen->strings[id - 1].pos = pos; put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4); put_u4le(gen, len); put_u4le(gen, pos); } else { free(*str); struct l2_generator_string *s = &gen->strings[id - 1]; put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4); put_u4le(gen, s->length); put_u4le(gen, s->pos); } } void l2_gen_string_copy(struct l2_generator *gen, char *str) { size_t id = l2_strset_get(&gen->stringset, str); if (id == 0) { char *s = strdup(str); l2_gen_string(gen, &s); } else { struct l2_generator_string *s = &gen->strings[id - 1]; put(gen, L2_OP_ALLOC_BUFFER_STATIC_U4); put_u4le(gen, s->length); put_u4le(gen, s->pos); } } void l2_gen_function(struct l2_generator *gen, l2_word pos) { put(gen, L2_OP_ALLOC_FUNCTION_U4); put_u4le(gen, pos); } void l2_gen_array(struct l2_generator *gen, l2_word count) { put(gen, L2_OP_ALLOC_ARRAY_U4); put_u4le(gen, count); } void l2_gen_namespace(struct l2_generator *gen) { put(gen, L2_OP_ALLOC_NAMESPACE); } void l2_gen_namespace_set(struct l2_generator *gen, char **ident) { size_t atom_id = l2_strset_put(&gen->atomset, ident); put(gen, L2_OP_NAMESPACE_SET_U4); put_u4le(gen, atom_id); } void l2_gen_namespace_set_copy(struct l2_generator *gen, char *ident) { size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); put(gen, L2_OP_NAMESPACE_SET_U4); put_u4le(gen, atom_id); } void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident) { size_t atom_id = l2_strset_put(&gen->atomset, ident); put(gen, L2_OP_NAMESPACE_LOOKUP_U4); put_u4le(gen, atom_id); } void l2_gen_namespace_lookup_copy(struct l2_generator *gen, char *ident) { size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); put(gen, L2_OP_NAMESPACE_LOOKUP_U4); put_u4le(gen, atom_id); } void l2_gen_array_lookup(struct l2_generator *gen, int number) { put(gen, L2_OP_ARRAY_LOOKUP_U4); put_u4le(gen, number); } void l2_gen_array_set(struct l2_generator *gen, int number) { put(gen, L2_OP_ARRAY_SET); put(gen, number); } void l2_gen_dynamic_lookup(struct l2_generator *gen) { put(gen, L2_OP_DYNAMIC_LOOKUP); } void l2_gen_dynamic_set(struct l2_generator *gen) { put(gen, L2_OP_DYNAMIC_SET); } void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) { size_t atom_id = l2_strset_put(&gen->atomset, ident); put(gen, L2_OP_STACK_FRAME_LOOKUP_U4); put_u4le(gen, atom_id); } void l2_gen_stack_frame_lookup_copy(struct l2_generator *gen, char *ident) { size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); put(gen, L2_OP_STACK_FRAME_LOOKUP_U4); put_u4le(gen, atom_id); } void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident) { size_t atom_id = l2_strset_put(&gen->atomset, ident); put(gen, L2_OP_STACK_FRAME_SET_U4); put_u4le(gen, atom_id); } void l2_gen_stack_frame_set_copy(struct l2_generator *gen, char *ident) { size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); put(gen, L2_OP_STACK_FRAME_SET_U4); put_u4le(gen, atom_id); } void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident) { size_t atom_id = l2_strset_put(&gen->atomset, ident); put(gen, L2_OP_STACK_FRAME_REPLACE_U4); put_u4le(gen, atom_id); } void l2_gen_stack_frame_replace_copy(struct l2_generator *gen, char *ident) { size_t atom_id = l2_strset_put_copy(&gen->atomset, ident); put(gen, L2_OP_STACK_FRAME_REPLACE_U4); put_u4le(gen, atom_id); } void l2_gen_func_call(struct l2_generator *gen, l2_word argc) { put(gen, L2_OP_FUNC_CALL_U4); put_u4le(gen, argc); } void l2_gen_func_call_infix(struct l2_generator *gen) { put(gen, L2_OP_FUNC_CALL_INFIX); }