aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-10-06 18:49:05 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-10-06 18:49:05 +0200
commit63a2cced4238af7d171e0b8807d887c435b4656b (patch)
treee08a23b3700ccd540c053d7c4cbe24bf7cf53d6c
parentf0cd9e4e8bc1e1b109fff627c75527ee7195c82e (diff)
downloadAGH-engineering-thesis-63a2cced4238af7d171e0b8807d887c435b4656b.tar.gz
AGH-engineering-thesis-63a2cced4238af7d171e0b8807d887c435b4656b.zip
add translation of relational operations and loops
l---------tests/wasm_compile_loop/Makefile1
-rw-r--r--tests/wasm_compile_loop/instructions.wat25
l---------tests/wasm_compile_loop/test.v1
-rw-r--r--tests/wasm_compile_loop/words_to_verify.mem4
-rw-r--r--tools/stack_machine_instruction.h48
-rw-r--r--tools/translate.c74
-rw-r--r--tools/translate_xmacro.h7
-rw-r--r--tools/wasm.h12
8 files changed, 114 insertions, 58 deletions
diff --git a/tests/wasm_compile_loop/Makefile b/tests/wasm_compile_loop/Makefile
new file mode 120000
index 0000000..e451c8b
--- /dev/null
+++ b/tests/wasm_compile_loop/Makefile
@@ -0,0 +1 @@
+../wasm_compile_simple_module/Makefile \ No newline at end of file
diff --git a/tests/wasm_compile_loop/instructions.wat b/tests/wasm_compile_loop/instructions.wat
new file mode 100644
index 0000000..02a75e0
--- /dev/null
+++ b/tests/wasm_compile_loop/instructions.wat
@@ -0,0 +1,25 @@
+(module
+ (memory 0 2)
+ (func $main
+ (local $counter i32)
+
+ ;; prepare offset for store operation later
+ (i32.const 0x0)
+
+ ;; initialize counter
+ (set_local $counter (i32.const 0))
+
+ ;; add numbers from 1 to 10
+ (i32.const 0)
+ (loop $again (param i32) (result i32)
+ (set_local $counter (i32.add
+ (get_local $counter)
+ (i32.const 1)))
+ (i32.add (get_local $counter))
+ (br_if $again (i32.lt_u
+ (get_local $counter)
+ (i32.const 10))))
+
+ ;; write computed sum (55 in dec, 37 in hex) at MEMORY_BOTTOM_ADDR
+ (i32.store offset=0x0 align=2))
+ (export "main" (func $main)))
diff --git a/tests/wasm_compile_loop/test.v b/tests/wasm_compile_loop/test.v
new file mode 120000
index 0000000..f0235d8
--- /dev/null
+++ b/tests/wasm_compile_loop/test.v
@@ -0,0 +1 @@
+../wasm_compile_simple_module/test.v \ No newline at end of file
diff --git a/tests/wasm_compile_loop/words_to_verify.mem b/tests/wasm_compile_loop/words_to_verify.mem
new file mode 100644
index 0000000..ef41c69
--- /dev/null
+++ b/tests/wasm_compile_loop/words_to_verify.mem
@@ -0,0 +1,4 @@
+// address value
+ 0FFFFC 23
+
+ 200 00000037
diff --git a/tools/stack_machine_instruction.h b/tools/stack_machine_instruction.h
index 003fa19..1f47c40 100644
--- a/tools/stack_machine_instruction.h
+++ b/tools/stack_machine_instruction.h
@@ -2,45 +2,6 @@
#include "wasm_compile.h"
-/*
- * TODO: this enum is to be removed; it it only still here as a cheat sheet
- * for use when defining missing inline functions for those instructions
- */
-enum instruction_code {
- STORE,
- STORE_P,
- STOREB,
- STOREB_P,
- STOREW,
- STOREW_P,
- LOAD,
- LOAD_P,
- LOADBZX,
- LOADBZX_P,
- LOADBSX,
- LOADBSX_P,
- LOADWZX,
- LOADWZX_P,
- LOADWSX,
- LOADWSX_P,
- HALT,
- NOP,
- SWAP,
- SET_SP,
- JUMP,
- TEE,
- GET_FRAME,
- CONST,
- CALL,
- ADD,
- SUB,
- DIV,
- MUL,
- DROP,
- RET,
- COND_JUMP
-};
-
#define DATA_NONE 0
#define DATA_KNOWN 1
#define DATA_KNOWN_21_BITS 2
@@ -156,6 +117,15 @@ Y(sub, 0x3001) /* 0011_0000_0000_0001 */
Y(div, 0x3002) /* 0011_0000_0000_0010 */
Y(mul, 0x3003) /* 0011_0000_0000_0011 */
Y(drop, 0x3004) /* 0011_0000_0000_0100 */
+Y(eq, 0x3007) /* 0011_0000_0000_0111 */
+Y(lt, 0x3008) /* 0011_0000_0000_1000 */
+Y(ult, 0x3009) /* 0011_0000_0000_1001 */
+Y(le, 0x300A) /* 0011_0000_0000_1010 */
+Y(ule, 0x300B) /* 0011_0000_0000_1011 */
+Y(gt, 0x300C) /* 0011_0000_0000_1100 */
+Y(ugt, 0x300D) /* 0011_0000_0000_1101 */
+Y(ge, 0x300E) /* 0011_0000_0000_1110 */
+Y(uge, 0x300F) /* 0011_0000_0000_1111 */
Y(ret, 0x3080) /* 0011_0000_1000_0000 */
X(cond_jump, 0x7080) /* 0111_0000_1xxx_xxxx */
X(cond_jump_n, 0x7100) /* 0111_0001_0xxx_xxxx */
diff --git a/tools/translate.c b/tools/translate.c
index 8b28aad..27532ad 100644
--- a/tools/translate.c
+++ b/tools/translate.c
@@ -259,17 +259,16 @@ static int typecheck_call(struct translation *data, struct function *callee)
return 0;
}
-static int typecheck_local_get(struct translation *data, uint32_t localidx)
+static int typecheck_local_get_set(struct translation *data, uint32_t localidx,
+ bool set)
{
uint32_t args_count = data->function->type->args.count;
char type = localidx < args_count ?
data->function->type->args.types[localidx] :
data->function->locals[localidx - args_count];
- if (rescheck_generic(&data->types_stack, type))
- return -1;
-
- return 0;
+ return (set ? argcheck_generic : rescheck_generic)
+ (&data->types_stack, type);
}
/** DEFINE INSTRUCTION TRANSLATION FUNCTIONS **/
@@ -277,6 +276,31 @@ static int typecheck_local_get(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)
+{
+ struct resulttype block_args, block_results;
+ char type_storage;
+ static const uint8_t loop_end_marker_code = WASM_END;
+ static const struct end_markers loop_end_markers = {
+ .count = 1,
+ .codes = &loop_end_marker_code
+ };
+
+ if (parse_blocktype(data->handle, &block_args, &block_results,
+ &type_storage, data->module))
+ goto fail;
+
+ if (translate_expr(data, &block_args, &block_results,
+ &loop_end_markers, NULL, true))
+ goto fail;
+
+ return 0;
+
+fail:
+ PRERR("Couldn't translate loop instruction\n");
+ return -1;
+}
+
static int _translate_if(struct translation *data)
{
struct types *backed_stack;
@@ -488,9 +512,7 @@ static int _translate_call(struct translation *data)
return i_call(ptr(target), &data->function->translated_body);
}
-static int typecheck_local_get(struct translation *data, uint32_t localidx);
-
-static int _translate_local_get(struct translation *data)
+static int translate_local_get_set(struct translation *data, bool set)
{
uint32_t localidx;
uint32_t args_count = data->function->type->args.count;
@@ -509,7 +531,7 @@ static int _translate_local_get(struct translation *data)
return -1;
}
- if (typecheck_local_get(data, localidx))
+ if (typecheck_local_get_set(data, localidx, set))
return -1;
offset_on_frame = all_locals_count - localidx + 1;
@@ -517,11 +539,27 @@ static int _translate_local_get(struct translation *data)
if (localidx >= args_count)
offset_on_frame -= 1;
- if (i_load (im(STACK_FRAME_BACKUP_ADDR), expr) ||
- i_load_p(im(4 * offset_on_frame), expr))
+ if (i_load(im(STACK_FRAME_BACKUP_ADDR), expr))
return -1;
- return 0;
+ if (set) {
+ return
+ i_swap ( expr) ||
+ i_store_p(im(4 * offset_on_frame), expr);
+ } else {
+ return
+ i_load_p(im(4 * offset_on_frame), expr);
+ }
+}
+
+static int _translate_local_get(struct translation *data)
+{
+ return translate_local_get_set(data, false);
+}
+
+static int _translate_local_set(struct translation *data)
+{
+ return translate_local_get_set(data, true);
}
static int _translate_const(struct translation *data)
@@ -610,12 +648,10 @@ static int translate_instr(struct translation *data, uint8_t wasm_opcode)
tc_routines = typecheck_routines + wasm_opcode;
- if (tc_routines->argcheck(&data->types_stack) ||
- tc_routines->rescheck(&data->types_stack) ||
- translation_routines[wasm_opcode](data))
- return -1;
-
- return 0;
+ return
+ tc_routines->argcheck(&data->types_stack) ||
+ translation_routines[wasm_opcode](data) ||
+ tc_routines->rescheck(&data->types_stack);
}
static int parse_blocktype(FILE *handle, struct resulttype *args,
@@ -666,7 +702,7 @@ static int parse_blocktype(FILE *handle, struct resulttype *args,
goto fail;
}
- if (typeidx <= module->functypes_count) {
+ if (typeidx >= module->functypes_count) {
PRERR(MSG_BAD_IDX("type index"));
goto fail;
}
diff --git a/tools/translate_xmacro.h b/tools/translate_xmacro.h
index 958d8d9..079fc74 100644
--- a/tools/translate_xmacro.h
+++ b/tools/translate_xmacro.h
@@ -5,6 +5,11 @@ TS (WASM_I32_ADD, add, i32_i32, i32)
TS (WASM_I32_SUB, sub, i32_i32, i32)
TS (WASM_I32_DIV_U, div, i32_i32, i32)
TS (WASM_I32_MUL, mul, i32_i32, i32)
+TS (WASM_I32_EQ, eq, i32_i32, i32)
+TS (WASM_I32_LT_S, lt, i32_i32, i32)
+TS (WASM_I32_LT_U, ult, i32_i32, i32)
+TS (WASM_I32_GT_S, gt, i32_i32, i32)
+TS (WASM_I32_GT_U, ugt, i32_i32, i32)
TLS(WASM_I32_LOAD, load_p, i32, i32)
TLS(WASM_I32_LOAD8_S, loadbsx_p, i32, i32)
@@ -19,9 +24,11 @@ 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_LOOP, loop, custom, custom)
TC (WASM_IF, if, i32, custom)
TC (WASM_BR, br, custom, custom)
TC (WASM_BR_IF, br_if, i32, custom)
TC (WASM_CALL, call, custom, custom)
TC (WASM_LOCAL_GET, local_get, empty, custom)
+TC (WASM_LOCAL_SET, local_set, custom, empty)
TC (WASM_I32_CONST, const, empty, i32)
diff --git a/tools/wasm.h b/tools/wasm.h
index 476f892..8333ce5 100644
--- a/tools/wasm.h
+++ b/tools/wasm.h
@@ -22,6 +22,7 @@
#define EXPORT_GLOBALIDX 0x03
/* WebAssembly opcodes */
+#define WASM_LOOP 0x03
#define WASM_IF 0x04
#define WASM_ELSE 0x05
#define WASM_END 0x0B
@@ -30,6 +31,7 @@
#define WASM_CALL 0x10
#define WASM_LOCAL_GET 0x20
+#define WASM_LOCAL_SET 0x21
#define WASM_I32_LOAD 0x28
#define WASM_I32_LOAD8_S 0x2C
@@ -43,6 +45,16 @@
#define WASM_I32_CONST 0x41
+#define WASM_I32_EQ 0x46
+#define WASM_I32_LT_S 0x48
+#define WASM_I32_LT_U 0x49
+#define WASM_I32_GT_S 0x4A
+#define WASM_I32_GT_U 0x4B
+#define WASM_I32_LE_S 0x4C
+#define WASM_I32_LE_U 0x4D
+#define WASM_I32_GE_S 0x4E
+#define WASM_I32_GE_U 0x4F
+
#define WASM_I32_ADD 0x6A
#define WASM_I32_SUB 0x6B
#define WASM_I32_MUL 0x6C