From 5e04a9626e2986fc40825d15cb09a274223381e9 Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Thu, 8 Oct 2020 19:18:43 +0200 Subject: translate webasm block of instructions + put instruction names as comments in generated code --- tools/assemble.c | 38 ++++++++++++++++++++------------------ tools/parse_module.c | 2 ++ tools/stack_machine_instruction.h | 7 ++++--- tools/translate.c | 35 ++++++++++++++++++++++++----------- tools/translate_xmacro.h | 1 + tools/wasm.h | 1 + tools/wasm_compile.c | 26 ++++++++++++++++++-------- tools/wasm_compile.h | 12 +++++++++--- 8 files changed, 79 insertions(+), 43 deletions(-) (limited to 'tools') diff --git a/tools/assemble.c b/tools/assemble.c index b8bd75e..bb8c8d4 100644 --- a/tools/assemble.c +++ b/tools/assemble.c @@ -20,7 +20,7 @@ void free_expr(struct instruction *expr) /* instructions are stored in a circular list */ int add_instruction(struct instruction **expr, uint16_t encoding, - struct instruction_data data) + struct instruction_data data, const char *name) { struct instruction *new; @@ -34,6 +34,7 @@ int add_instruction(struct instruction **expr, uint16_t encoding, new->address_assigned = false; new->encoding = encoding; new->data = data; + new->name = name; if (!*expr) { new->next = new; @@ -113,11 +114,13 @@ static uint16_t im_instruction(uint16_t payload) } static void encode_instruction(struct instruction *instruction, - uint16_t *memory) + struct translated_word *memory) { uint32_t im = 0; uint16_t encoding = instruction->encoding; - uint16_t *dest = memory + instruction->address / 2; + struct translated_word *dest = memory + instruction->address / 2; + + dest->instr = instruction; if (instruction->data.info == DATA_INSTR_ADDR) { im = (*instruction->data.data.ptr)->address; @@ -132,17 +135,18 @@ static void encode_instruction(struct instruction *instruction, case DATA_INSTR_ADDR : case DATA_ADDR_AFTER : case DATA_KNOWN : - *(dest++) = im_instruction(im >> 22); + (dest++)->contents = im_instruction(im >> 22); case DATA_KNOWN_21_BITS : - *(dest++) = im_instruction(im >> 7); + (dest++)->contents = im_instruction(im >> 7); case DATA_KNOWN_6_BITS : encoding |= im & 0x7F; } - *dest = encoding; + dest->contents = encoding; } -static void encode_expr(struct instruction *expr, uint16_t *memory) +static void encode_expr(struct instruction *expr, + struct translated_word *memory) { struct instruction *tmp = expr; @@ -152,14 +156,14 @@ static void encode_expr(struct instruction *expr, uint16_t *memory) } while (tmp != expr); } -int assemble(uint32_t memory_size, uint16_t memory[memory_size], +int assemble(uint32_t memory_size, struct translated_word memory[memory_size], struct module *module) { uint32_t i; struct function *main_function = NULL; uint32_t current_address; uint64_t function_size; - struct instruction *startup = NULL; + struct instruction **startup = &module->startup; unsigned short startup_size; int retval = -1; @@ -181,13 +185,13 @@ int assemble(uint32_t memory_size, uint16_t memory[memory_size], * We're first writing some value at STACK_FRAME_BACKUP_ADDR to be able * to check, if the functions we call restore frame address properly */ - if (i_const(im(0x23), &startup) || - i_store(im(STACK_FRAME_BACKUP_ADDR), &startup) || - i_call (ptr(&main_function->translated_body), &startup) || - i_halt ( &startup)) + if (i_const(im(0x23), startup) || + i_store(im(STACK_FRAME_BACKUP_ADDR), startup) || + i_call (ptr(&main_function->translated_body), startup) || + i_halt ( startup)) goto fail; - startup_size = estimate_expr_size(startup); + startup_size = estimate_expr_size(*startup); i = module->functions_count; current_address = CODE_TOP_ADDR; @@ -209,13 +213,13 @@ int assemble(uint32_t memory_size, uint16_t memory[memory_size], assign_addresses_and_sizes(module->functions[i].translated_body, module->functions[i].start_addr); - assign_addresses_and_sizes(startup, 0x0); + assign_addresses_and_sizes(*startup, 0x0); i = module->functions_count; while (i--) encode_expr(module->functions[i].translated_body, memory); - encode_expr(startup, memory); + encode_expr(*startup, memory); retval = 0; @@ -223,7 +227,5 @@ fail: if (retval) PRERR("Couldn't assemble code for stack machine\n"); - free_expr(startup); - return retval; } diff --git a/tools/parse_module.c b/tools/parse_module.c index 3f9895c..8c519ab 100644 --- a/tools/parse_module.c +++ b/tools/parse_module.c @@ -84,6 +84,8 @@ void free_module(struct module *module) free_targets(module->targets); + free_expr(module->startup); + free(module); } diff --git a/tools/stack_machine_instruction.h b/tools/stack_machine_instruction.h index 1f47c40..15c870b 100644 --- a/tools/stack_machine_instruction.h +++ b/tools/stack_machine_instruction.h @@ -23,6 +23,7 @@ struct instruction { bool address_assigned; uint16_t encoding; struct instruction_data data; + const char *name; }; #define NO_DATA ((struct instruction_data) { \ @@ -76,21 +77,21 @@ inline static struct instruction_data ptr_after(struct instruction **val) { } int add_instruction(struct instruction **expr, uint16_t encoding, - struct instruction_data data); + struct instruction_data data, const char *name); /* Define stack machine instructions, that take immediate operands */ #define X(instr, encoding) \ inline static int i_##instr(struct instruction_data data, \ struct instruction **expr) \ { \ - return add_instruction(expr, encoding, data); \ + return add_instruction(expr, encoding, data, #instr); \ } /* Define stack machine instructions, that *don't* take immediate operands */ #define Y(instr, encoding) \ inline static int i_##instr(struct instruction **expr) \ { \ - return add_instruction(expr, encoding, NO_DATA); \ + return add_instruction(expr, encoding, NO_DATA, #instr); \ } X(store, 0x7E00) /* 0111_1110_0xxx_xxxx */ diff --git a/tools/translate.c b/tools/translate.c index 27532ad..00191a3 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -276,7 +276,7 @@ static int typecheck_local_get_set(struct translation *data, uint32_t localidx, /* Translate complex - those routines have to be defined manually */ #define TC(wasm_opcode, name, argtypes, restype) -static int _translate_loop(struct translation *data) +static int translate_block_loop(struct translation *data, bool loop) { struct resulttype block_args, block_results; char type_storage; @@ -291,7 +291,7 @@ static int _translate_loop(struct translation *data) goto fail; if (translate_expr(data, &block_args, &block_results, - &loop_end_markers, NULL, true)) + &loop_end_markers, NULL, loop)) goto fail; return 0; @@ -301,6 +301,16 @@ fail: return -1; } +static int _translate_block(struct translation *data) +{ + return translate_block_loop(data, false); +} + +static int _translate_loop(struct translation *data) +{ + return translate_block_loop(data, true); +} + static int _translate_if(struct translation *data) { struct types *backed_stack; @@ -343,7 +353,7 @@ static int _translate_if(struct translation *data) data->types_stack = backed_stack; if (retval) - goto fail; + goto fail; if (i_jump(ptr_after(&else_end->instr), expr)) goto fail; @@ -422,7 +432,7 @@ static int _translate_br(struct translation *data) i_load_p(im(-4 * (offset_dst - 1)), expr) || i_swap ( expr) || i_load_p(im(-4 * offset_dst), expr) || - i_add_sp(im(-4 * (shift + 2)), expr)) + i_add_sp(im(4 * (shift + 2)), expr)) goto fail; for (i = 0; i < arity; i++) { @@ -615,11 +625,11 @@ static int translate_load_store(struct translation *data, /** DEFINE TRANSLATION FUNCTIONS POINTER ARRAY **/ /* Translate complex */ -#define TC(wasm_opcode, name, argtypes, restype) \ +#define TC(wasm_opcode, name, argtypes, restype) \ [wasm_opcode] = _translate_##name, /* Translate Simple */ -#define TS(wasm_opcode, sm_instr, argtypes, restype) \ +#define TS(wasm_opcode, sm_instr, argtypes, restype) \ TC(wasm_opcode, sm_instr, dummy, dummy) /* Translate load/store */ @@ -734,6 +744,7 @@ static struct target *add_target(struct module *module) } static struct label *add_label(struct translation *data, struct target *target, + uint32_t values_popped, struct resulttype *arity) { struct label *lbl; @@ -750,6 +761,7 @@ static struct label *add_label(struct translation *data, struct target *target, lbl->arity = arity; lbl->values_on_stack = data->labels ? data->labels->values_on_stack : 0; lbl->values_on_stack += stack_size(data->types_stack); + lbl->values_on_stack -= values_popped; data->labels = lbl; @@ -777,7 +789,7 @@ static int translate_expr(struct translation *data, struct resulttype *args, if (continuation_at_start) continuation->instr = data->function->translated_body->prev; - label = add_label(data, continuation, + label = add_label(data, continuation, args ? args->count : 0, continuation_at_start ? args : results); if (!label) @@ -918,9 +930,11 @@ int translate(FILE *handle, struct function *function, struct module *module) goto fail; /* function epilogue */ + if (i_load (im(STACK_FRAME_BACKUP_ADDR), expr)) + goto fail; + if (function->type->results.count) { - if (i_load (im(STACK_FRAME_BACKUP_ADDR), expr) || - i_swap ( expr) || + if (i_swap ( expr) || i_store_p(im(4 * (2 + all_locals_count - 1)), expr) || i_load (im(STACK_FRAME_BACKUP_ADDR), expr) || i_tee ( expr) || @@ -932,8 +946,7 @@ int translate(FILE *handle, struct function *function, struct module *module) goto fail; } else { /* It's a bit shorter if we don't return anything */ - if (i_load (im(STACK_FRAME_BACKUP_ADDR), expr) || - i_tee ( expr) || + if (i_tee ( expr) || i_tee ( expr) || i_load_p (im(4 * (1 + locals_count)), expr) || i_store_p(im(4 * (2 + all_locals_count - 1)), expr) || diff --git a/tools/translate_xmacro.h b/tools/translate_xmacro.h index 079fc74..e906261 100644 --- a/tools/translate_xmacro.h +++ b/tools/translate_xmacro.h @@ -24,6 +24,7 @@ TLS(WASM_I32_STORE16, storew_p, i32_i32, empty) * There are more checks to be performed in case of if and br_if, but we do them * another way and only check for the i32 condition value here. */ +TC (WASM_BLOCK, block, custom, custom) TC (WASM_LOOP, loop, custom, custom) TC (WASM_IF, if, i32, custom) TC (WASM_BR, br, custom, custom) diff --git a/tools/wasm.h b/tools/wasm.h index 8333ce5..afa1908 100644 --- a/tools/wasm.h +++ b/tools/wasm.h @@ -22,6 +22,7 @@ #define EXPORT_GLOBALIDX 0x03 /* WebAssembly opcodes */ +#define WASM_BLOCK 0x02 #define WASM_LOOP 0x03 #define WASM_IF 0x04 #define WASM_ELSE 0x05 diff --git a/tools/wasm_compile.c b/tools/wasm_compile.c index 64988c8..c455541 100644 --- a/tools/wasm_compile.c +++ b/tools/wasm_compile.c @@ -1,24 +1,33 @@ #include "wasm_compile.h" +#include "stack_machine_instruction.h" -void print_instructions(uint32_t count, uint16_t instructions[count]) +void print_instructions(uint32_t count, + struct translated_word memory[count]) { uint32_t i; char binary[17]; - uint16_t instruction; + uint16_t bits; int j; binary[16] = '\0'; for (i = 0; i < count; i++) { - instruction = instructions[i]; + bits = memory[i].contents; j = 16; while (j--) { - binary[j] = (instruction & 1) ? '1' : '0'; - instruction >>= 1; + binary[j] = (bits & 1) ? '1' : '0'; + bits >>= 1; } - puts(binary); + printf(binary); + + if (memory[i].instr) { + printf(" // 0x%03lx %s", (long) i, + memory[i].instr->name); + } + + putchar('\n'); } } @@ -26,7 +35,7 @@ int main(int argc, char **argv) { FILE *handle = NULL; struct module *module = NULL; - uint16_t *translated_instructions = NULL; + struct translated_word *translated_instructions = NULL; char retval = -1; if (argc < 2) { @@ -46,7 +55,8 @@ int main(int argc, char **argv) if (!module) goto fail; - translated_instructions = calloc(1, CODE_TOP_ADDR); + translated_instructions = calloc(1, CODE_TOP_ADDR * + sizeof(struct translated_word)); if (!translated_instructions) { PRERR(MSG_ALLOC_FAIL(CODE_TOP_ADDR)); diff --git a/tools/wasm_compile.h b/tools/wasm_compile.h index 4cee1bb..c5ff49c 100644 --- a/tools/wasm_compile.h +++ b/tools/wasm_compile.h @@ -11,8 +11,8 @@ #define STACK_FRAME_BACKUP_ADDR 0x0FFFFC #define STACK_TOP_ADDR 0x0FFFFC #define CODE_BOTTOM_ADDR 0x000000 -#define CODE_TOP_ADDR 0x000200 -#define MEMORY_BOTTOM_ADDR 0x000200 +#define CODE_TOP_ADDR 0x000400 +#define MEMORY_BOTTOM_ADDR 0x000400 /* Error messages */ #define MSG_SIZE_OVERFLOW "Number overflows size_t\n" @@ -70,6 +70,12 @@ struct module { uint32_t exports_count; struct export *exports; struct target *targets; + struct instruction *startup; +}; + +struct translated_word { + uint16_t contents; + struct instruction *instr; }; int leb_32(FILE *handle, uint32_t *result, bool with_sign); @@ -94,7 +100,7 @@ struct module *parse_module(FILE *handle); int translate(FILE *handle, struct function *function, struct module *module); -int assemble(uint32_t memory_size, uint16_t memory[memory_size], +int assemble(uint32_t memory_size, struct translated_word memory[memory_size], struct module *module); #endif /* WASM_COMPILE_H */ -- cgit v1.2.3