From 882b9fcbad47a4da09127ca184a5c859632f1368 Mon Sep 17 00:00:00 2001 From: partic <1596067968@qq.com> Date: Tue, 4 Jul 2023 20:16:16 +0800 Subject: [PATCH] implement Extended Constant Expressions --- CMakeLists.txt | 2 +- README.md | 4 +- pwart/def.h | 9 +++ pwart/extfunc.c | 145 +++++++++++++++++++++++++++++++++++------------ tests/Makefile | 2 +- tests/test1.wat | 11 ++++ tests/testmain.c | 14 +++++ 7 files changed, 147 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bc8dce..68623da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ endif() if (BUILD_TESTING) enable_testing() - execute_process(COMMAND ${WAT2WASM} "--enable-multi-memory" "test1.wat" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests" COMMAND_ECHO STDOUT) + execute_process(COMMAND ${WAT2WASM} "--enable-multi-memory" "--enable-extended-const" "test1.wat" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests" COMMAND_ECHO STDOUT) execute_process(COMMAND ${WAT2WASM} "--enable-multi-memory" "extension1.wat" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests" COMMAND_ECHO STDOUT) execute_process(COMMAND ${WAT2WASM} "unary.wat" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests" COMMAND_ECHO STDOUT) execute_process(COMMAND ${WAT2WASM} "binary.wat" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests" COMMAND_ECHO STDOUT) diff --git a/README.md b/README.md index 0acf71a..37d3d20 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Multi-value Non-trapping Float-to-int Conversions (For performance, the behavior depend on the host.) -Bulk Memory Operations(Conditional Segment Initialization is not support yet.) +Bulk Memory Operations(Conditional Segment Initialization is not supported yet.) Memory64(support i64 index, offset and align are still 32bit.) @@ -98,6 +98,8 @@ Reference types Multiple memories +Extended Constant Expressions + Simple namespace support ## NOT Implemented diff --git a/pwart/def.h b/pwart/def.h index d3613d1..8937e01 100644 --- a/pwart/def.h +++ b/pwart/def.h @@ -500,6 +500,15 @@ static struct{ #define WASMOPC_i32_shl 0x74 #define WASMOPC_i64_shl 0x86 +#define WASMOPC_i32_add 0x6a +#define WASMOPC_i32_sub 0x6b +#define WASMOPC_i32_mul 0x6c +#define WASMOPC_i64_add 0x7c +#define WASMOPC_i64_sub 0x7d +#define WASMOPC_i64_mul 0x7e + +#define WASMOPC_end 0x0b + static struct pwart_global_compile_config pwart_gcfg={ .stack_flags=0, .misc_flags=PWART_MISC_FLAGS_LOCALS_ZERO_INIT diff --git a/pwart/extfunc.c b/pwart/extfunc.c index 289f100..cf53dee 100644 --- a/pwart/extfunc.c +++ b/pwart/extfunc.c @@ -481,48 +481,119 @@ static Type func_type_ref_ref_i32_void={.params=types_ref_ref_i32,.results=types static Type func_type_memoryfill={.params=types_ref_i32_i32_ref_i32,.results=types_void}; static char *waexpr_run_const(ModuleCompiler *m, void *result) { - int opcode=m->bytes[m->pc]; - m->pc++; - switch (opcode) { - case 0x41: // i32.const - *(uint32_t *)result = read_LEB_signed(m->bytes, &m->pc, 32); - break; - case 0x42: // i64.const - *(uint64_t *)result = read_LEB_signed(m->bytes, &m->pc, 64); - break; - case 0x43: // f32.const - *(float *)result = *(float *)(m->bytes + m->pc); - m->pc += 4; - break; - case 0x44: // f64.const - *(double *)result = *(double *)(m->bytes + m->pc); - m->pc += 8; - break; - case 0x23: // global.get - { - uint32_t arg = read_LEB(m->bytes, &m->pc, 32); - StackValue *sv = dynarr_get(m->globals, StackValue, arg); - if (stackvalue_GetSizeAndAlign(sv, NULL) == 8) { - *(uint64_t *)result = *(uint64_t *)(sv->val.opw); - } else { - *(uint32_t *)result = *(uint32_t *)(sv->val.opw); + int opcode=0; + //const stack + uint64_t stack[16]; + void *sp=&stack; + int eof=0; + while(m->pc<=m->byte_count && !eof){ + opcode=m->bytes[m->pc]; + m->pc++; + switch (opcode) { + case 0x41: // i32.const + *(uint32_t *)sp = read_LEB_signed(m->bytes, &m->pc, 32); + sp+=4; + break; + case 0x42: // i64.const + *(uint64_t *)sp = read_LEB_signed(m->bytes, &m->pc, 64); + sp+=8; + break; + case 0x43: // f32.const + //use memmove to avoid align error + memmove(sp,m->bytes + m->pc,4); + m->pc += 4; + sp+=4; + break; + case 0x44: // f64.const + //use memmove to avoid align error + memmove(sp,m->bytes + m->pc,8); + m->pc += 8; + sp+=8; + break; + case 0x23: // global.get + { + uint32_t arg = read_LEB(m->bytes, &m->pc, 32); + StackValue *sv = dynarr_get(m->globals, StackValue, arg); + if (stackvalue_GetSizeAndAlign(sv, NULL) == 8) { + *(uint64_t *)sp = *(uint64_t *)(sv->val.opw); + sp+=8; + } else { + *(uint32_t *)sp = *(uint32_t *)(sv->val.opw); + sp+=4; + } + } break; + case 0xd0: //ref.null + *(void **)sp=NULL; + sp+=m->target_ptr_size/8; + break; + case 0xd2: //ref.func + { + uint32_t arg = read_LEB(m->bytes, &m->pc, 32); + *(WasmFunction **)sp = dynarr_get(m->functions,WasmFunction,arg); + sp+=m->target_ptr_size/8; + }break; + case WASMOPC_i32_add: + { + uint32_t *arg1=((void *)sp)-8; + uint32_t *arg2=arg1+1; + sp-=8; + *(uint32_t *)sp=*arg1+*arg2; + sp+=4; + }break; + case WASMOPC_i32_sub: + { + uint32_t *arg1=((void *)sp)-8; + uint32_t *arg2=arg1+1; + sp-=8; + *(uint32_t *)sp=*arg1-*arg2; + sp+=4; + }break; + case WASMOPC_i32_mul: + { + uint32_t *arg1=((void *)sp)-8; + uint32_t *arg2=arg1+1; + sp-=8; + *(uint32_t *)sp=(*arg1) * (*arg2); + sp+=4; + }break; + case WASMOPC_i64_add: + { + uint64_t *arg1=((void *)sp)-16; + uint64_t *arg2=arg1+1; + sp-=16; + *(uint64_t *)sp=*arg1+*arg2; + sp+=8; + }break; + case WASMOPC_i64_sub: + { + uint64_t *arg1=((void *)sp)-16; + uint64_t *arg2=arg1+1; + sp-=16; + *(uint64_t *)sp=*arg1-*arg2; + sp+=8; + }break; + case WASMOPC_i64_mul: + { + uint64_t *arg1=((void *)sp)-16; + uint64_t *arg2=arg1+1; + sp-=16; + *(uint64_t *)sp=(*arg1) * (*arg2); + sp+=8; + }break; + case WASMOPC_end: + eof=1; + m->pc--; + break; + default: + return "Unsupport const expr"; + break; } - } break; - case 0xd0: //ref.null - *(void **)result=NULL; - break; - case 0xd2: //ref.func - { - uint32_t arg = read_LEB(m->bytes, &m->pc, 32); - *(WasmFunction **)result = dynarr_get(m->functions,WasmFunction,arg); - } - default: - return "Unsupport const expr"; - break; } + if(m->bytes[m->pc]!=0xb){ return "const expr miss end instruction."; } + memcpy(result,&stack,sp-(void *)stack); m->pc++; return NULL; } diff --git a/tests/Makefile b/tests/Makefile index e449e4a..a92c7bf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ include $(PWART_SOURCE_ROOT)/pwart/make_config.mk test:build_pwart - rm testexe || rm testexe.exe $(CC) $(PWART_CFLAGS) $(CFLAGS) -o testexe testmain.c $(PWART_LDFLAGS) $(LDFLAGS) - $(WAT2WASM) --enable-multi-memory test1.wat + $(WAT2WASM) --enable-multi-memory --enable-extended-const test1.wat $(WAT2WASM) unary.wat $(WAT2WASM) binary.wat $(WAT2WASM) control.wat diff --git a/tests/test1.wat b/tests/test1.wat index abbd9ef..046b8e8 100644 --- a/tests/test1.wat +++ b/tests/test1.wat @@ -18,6 +18,7 @@ (elem 0 (i32.const 0) $addTwo ) (global $one i32 (i32.const 1)) (global $two i32 (i32.const 2)) + (global $three (mut i32) (i32.add (i32.const 1)(i32.const 2))) ;; function 0 (func $nop @@ -270,9 +271,19 @@ call $ref_string_length ) + ;; function 10 expect 4 + (func $miscTest1 (result i32) + global.get $three + i32.const 1 + i32.add + global.set $three + global.get $three + ) + (export "addTwo" (func $addTwo)) (export "test1" (func $test1)) (export "test2" (func $test2)) (export "test3" (func $test3)) (export "builtinFuncTest" (func $builtinFuncTest)) + (export "miscTest1" (func $miscTest1)) ) \ No newline at end of file diff --git a/tests/testmain.c b/tests/testmain.c index 758a13c..8385b6e 100644 --- a/tests/testmain.c +++ b/tests/testmain.c @@ -99,6 +99,9 @@ int test1() { pwart_wasm_function fib_main = pwart_get_export_function(ctx, "fib_main"); pwart_wasm_function builtinFuncTest = pwart_get_export_function(ctx, "builtinFuncTest"); + pwart_wasm_function miscTest1 = + pwart_get_export_function(ctx, "miscTest1"); + pwart_free_module_compiler(m); @@ -232,6 +235,17 @@ int test1() { return 0; } + // miscTest1 test + sp = stackbase; + sp = stackbase; + pwart_call_wasm_function(miscTest1, sp); + ri32 = geti32(&sp); + printf("11.miscTest1 test, expect %x got %x\n", + 4,ri32); + if (4!=ri32) { + return 0; + } + pwart_free_module_state(ctx); } free(data);