extensions
Vova 3 years ago
commit 3c0a7c159a

@ -528,7 +528,7 @@ jobs:
run: |
mkdir build
cd build
g++ -xc++ -Dd_m3HasWASI \
clang -xc++ -Dd_m3HasWASI \
-I../source ../source/*.c ../platforms/app/main.c \
-O3 -g0 -lm \
-o wasm3
@ -546,7 +546,7 @@ jobs:
run: |
mkdir build
cd build
g++ -xc++ -Dd_m3HasWASI -DDEBUG \
clang -xc++ -Dd_m3HasWASI -DDEBUG \
-Dd_m3EnableOpTracing=1 \
-Dd_m3EnableStrace=1 \
-Dd_m3LogParse=1 \

@ -98,6 +98,7 @@ Wasm3 started as a research project and remains so by many means. Evaluating the
## Further Resources
[Demos](./docs/Demos.md)
[Cookbook](./docs/Cookbook.md)
[Installation instructions](./docs/Installation.md)
[Build and Development instructions](./docs/Development.md)
[Supported Hardware](./docs/Hardware.md)

@ -0,0 +1,394 @@
# WASM module examples
### Rust WASI app
Create a new project:
```sh
$ cargo new --bin hello
$ cd hello
$ rustup target add wasm32-wasi
```
Build and run:
```sh
$ cargo build --release --target wasm32-wasi
$ wasm3 ./target/wasm32-wasi/release/hello.wasm
Hello, world!
```
### AssemblyScript WASI app
Create `hello.ts`:
```ts
import "wasi"
import {Console} from "as-wasi"
Console.log('Hello World!');
```
Create `package.json`:
```json
{
"scripts": {
"asbuild:debug": "asc hello.ts -b hello.wasm --debug",
"asbuild:optimized": "asc hello.ts -b hello.wasm -O3s --noAssert",
"asbuild:tiny": "asc hello.ts -b hello.wasm -O3z --noAssert --runtime stub --use abort=",
"build": "npm run asbuild:optimized"
},
"devDependencies": {
"assemblyscript": "*",
"as-wasi": "*"
}
}
```
Build and run:
```sh
$ npm install
$ npm run build
$ wasm3 hello.wasm
Hello World!
```
### TinyGo WASI app
Create `hello.go`:
```go
package main
import "fmt"
func main() {
fmt.Printf("Hello, %s!\n", "world")
}
```
Build and run:
```sh
$ tinygo build -o hello.wasm -target wasi -no-debug hello.go
$ wasm3 hello.wasm
Hello, world!
```
### Zig WASI app
Create `hello.zig`:
```zig
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello, {s}!\n", .{"world"});
}
```
Build and run:
```sh
$ zig build-exe -O ReleaseSmall -target wasm32-wasi hello.zig
$ wasm3 hello.wasm
Hello, world!
```
## Zig library
Create `add.zig`:
```zig
export fn add(a: i32, b: i32) i64 {
return a + b;
}
```
Build and run:
```sh
$ zig build-lib add.zig -O ReleaseSmall -target wasm32-freestanding
$ wasm3 --repl add.wasm
wasm3> add 1 2
Result: 3
```
### C/C++ WASI app
The easiest way to start is to use [Wasienv](https://github.com/wasienv/wasienv).
Create `hello.cpp`:
```cpp
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
return 0;
}
```
Or `hello.c`:
```c
#include <stdio.h>
int main() {
printf("Hello, %s!\n", "world");
return 0;
}
```
Build and run:
```sh
$ wasic++ -O3 hello.cpp -o hello.wasm
$ wasicc -O3 hello.c -o hello.wasm
$ wasm3 hello.wasm
Hello World!
```
Limitations:
- `setjmp/longjmp` and `C++ exceptions` are not available
- no support for `threads` and `atomics`
- no support for `dynamic libraries`
### WAT WASI app
Create `hello.wat`:
```wat
(module
;; wasi_snapshot_preview1!fd_write(file_descriptor, *iovs, iovs_len, nwritten) -> status_code
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; Put a message to linear memory at offset 32
(data (i32.const 32) "Hello, world!\n")
(func $main (export "_start")
;; Create a new io vector at address 0x4
(i32.store (i32.const 4) (i32.const 32)) ;; iov.iov_base - pointer to the start of the message
(i32.store (i32.const 8) (i32.const 14)) ;; iov.iov_len - length of the message
(call $fd_write
(i32.const 1) ;; file_descriptor - 1 for stdout
(i32.const 4) ;; *iovs - pointer to the io vector
(i32.const 1) ;; iovs_len - count of items in io vector
(i32.const 20) ;; nwritten - where to store the number of bytes written
)
drop ;; discard the WASI status code
)
)
```
Build and run:
```sh
$ wat2wasm hello.wat -o hello.wasm
$ wasm3 hello.wasm
Hello, world!
```
### WAT library
Create `swap.wat`:
```wat
(module
(func (export "swap") (param i32 i32) (result i32 i32)
(get_local 1)
(get_local 0)
)
)
```
Build and run:
```sh
$ wat2wasm swap.wat -o swap.wasm
$ wasm3 --repl swap.wasm
wasm3> :invoke swap 123 456
Result: 456:i32, 123:i32
```
# Tracing
Drag'n'drop any of the WASI apps to [`WebAssembly.sh`](https://webassembly.sh/) and run:
```sh
$ wasm3-strace /tmp/hello.wasm
```
The execution trace will be produced:
```js
_start () {
__wasilibc_init_preopen () {
malloc (i32: 16) {
dlmalloc (i32: 16) {
sbrk (i32: 0) {
} = 131072
sbrk (i32: 65536) {
```
<details>
<summary>Click to expand!</summary>
```js
} = 131072
} = 131088
} = 131088
calloc (i32: 24, i32: 0) {
dlmalloc (i32: 96) {
} = 131120
memset (i32: 131120, i32: 65504, i32: 0) {
} = 131120
} = 131120
po_map_assertvalid (i32: 131088) {
}
po_map_assertvalid (i32: 131088) {
}
}
wasi_unstable!fd_prestat_get(3, 65528) { <native> } = 0
malloc (i32: 2) {
dlmalloc (i32: 2) {
} = 131232
} = 131232
wasi_unstable!fd_prestat_dir_name(3, 131232, 1) { <native> } = 0
__wasilibc_register_preopened_fd (i32: 3, i32: 131120) {
po_map_assertvalid (i32: 131088) {
}
po_map_assertvalid (i32: 131088) {
}
strdup (i32: 131232) {
strlen (i32: 131232) {
} = 1
malloc (i32: 2) {
dlmalloc (i32: 2) {
} = 131248
} = 131248
memcpy (i32: 131248, i32: 131233, i32: 131232) {
} = 131248
} = 131248
wasi_unstable!fd_fdstat_get(3, 65496) { <native> } = 0
po_map_assertvalid (i32: 131088) {
}
po_map_assertvalid (i32: 131088) {
}
} = 0
free (i32: 131232) {
dlfree (i32: 131232) {
}
}
wasi_unstable!fd_prestat_get(4, 65528) { <native> } = 0
malloc (i32: 2) {
dlmalloc (i32: 2) {
} = 131232
} = 131232
wasi_unstable!fd_prestat_dir_name(4, 131232, 1) { <native> } = 0
__wasilibc_register_preopened_fd (i32: 4, i32: 131120) {
po_map_assertvalid (i32: 131088) {
}
po_map_assertvalid (i32: 131088) {
}
strdup (i32: 131232) {
strlen (i32: 131232) {
} = 1
malloc (i32: 2) {
dlmalloc (i32: 2) {
} = 131264
} = 131264
memcpy (i32: 131264, i32: 131233, i32: 131232) {
} = 131264
} = 131264
wasi_unstable!fd_fdstat_get(4, 65496) { <native> } = 0
po_map_assertvalid (i32: 131088) {
}
po_map_assertvalid (i32: 131088) {
}
} = 0
free (i32: 131232) {
dlfree (i32: 131232) {
}
}
wasi_unstable!fd_prestat_get(5, 65528) { <native> } = 8
__wasm_call_ctors () {
}
__original_main () {
printf (i32: 65536, i32: 0) {
vfprintf (i32: 69512, i32: 0, i32: 65536) {
printf_core (i32: 0, i32: -1, i32: 65536, i32: -16, i32: 65480) {
} = 0
__towrite (i32: 69512) {
} = 0
printf_core (i32: 69512, i32: 8, i32: 65536, i32: -1, i32: 65480) {
__fwritex (i32: 65536, i32: 0, i32: 7) {
memcpy (i32: 68472, i32: 0, i32: 65536) {
} = 68472
} = 7
__fwritex (i32: 65543, i32: 0, i32: 0) {
memcpy (i32: 68479, i32: 0, i32: 65543) {
} = 68479
} = 0
pop_arg (i32: 64456, i32: 0, i32: 9) {
}
strnlen (i32: 65548, i32: 0) {
memchr (i32: 65548, i32: 4, i32: 0) {
} = 65553
} = 5
__fwritex (i32: 67222, i32: 65553, i32: 0) {
memcpy (i32: 68479, i32: 0, i32: 67222) {
} = 68479
} = 0
__fwritex (i32: 65548, i32: 65553, i32: 5) {
memcpy (i32: 68479, i32: 0, i32: 65548) {
} = 68479
} = 5
__fwritex (i32: 65545, i32: 0, i32: 2) {
__stdout_write (i32: 69512, i32: 0, i32: 65545) {
__isatty (i32: 1) {
wasi_unstable!fd_fdstat_get(1, 64376) { <native> } = 0
} = 1
__stdio_write (i32: 69512, i32: 64368, i32: 65545) {
writev (i32: 1, i32: -16, i32: 64384) {
Hello, world!
wasi_unstable!fd_write(1, 64384, 2, 64380) { <native> } = 0
} = 14
} = 2
} = 2
memcpy (i32: 68472, i32: -1, i32: 65547) {
} = 68472
} = 2
} = 14
} = 14
} = 14
} = 0
__prepare_for_exit () {
dummy () {
}
__stdio_exit () {
__ofl_lock () {
} = 69504
}
}
}
```
</details>
# Gas Metering
```sh
$ npm install -g wasm-metering
$ wasm-meter hello.wasm hello-metered.wasm
$ wasm3 hello-metered.wasm
Warning: Gas is limited to 500000000.0000
Hello, world!
Gas used: 20.8950
$ wasm3 --gas-limit 10 hello-metered.wasm
Warning: Gas is limited to 10.0000
Gas used: 10.0309
Error: [trap] Out of gas
```
# Other resources
- [WebAssembly by examples](https://wasmbyexample.dev/home.en-us.html) by Aaron Turner
- [Writing WebAssembly](https://docs.wasmtime.dev/wasm.html) in Wasmtime docs

@ -43,6 +43,7 @@ int wasm_bins_qty = 0;
#if defined(GAS_LIMIT)
static int64_t initial_gas = GAS_FACTOR * GAS_LIMIT;
static int64_t current_gas = GAS_FACTOR * GAS_LIMIT;
static bool is_gas_metered = false;
@ -208,6 +209,15 @@ M3Result repl_load_hex (u32 fsize)
return result;
}
void print_gas_used()
{
#if defined(GAS_LIMIT)
if (is_gas_metered) {
fprintf(stderr, "Gas used: %0.4f\n", (double)(initial_gas - current_gas) / GAS_FACTOR);
}
#endif
}
void print_backtrace()
{
IM3BacktraceInfo info = m3_GetBacktrace(runtime);
@ -253,6 +263,8 @@ M3Result repl_call (const char* name, int argc, const char* argv[])
result = m3_CallArgv(func, 0, NULL);
print_gas_used();
if (result == m3Err_trapExit) {
exit(wasi_ctx->exit_code);
}
@ -273,11 +285,7 @@ M3Result repl_call (const char* name, int argc, const char* argv[])
result = m3_CallArgv (func, argc, argv);
#if defined(GAS_LIMIT)
if (is_gas_metered) {
fprintf(stderr, "Gas used: %0.4f\n", (double)((GAS_FACTOR * GAS_LIMIT) - current_gas) / GAS_FACTOR);
}
#endif
print_gas_used();
if (result) return result;
@ -297,8 +305,10 @@ M3Result repl_call (const char* name, int argc, const char* argv[])
switch (m3_GetRetType(func, i)) {
case c_m3Type_i32: fprintf (stderr, "Result: %" PRIi32 "\n", *(i32*)valptrs[i]); break;
case c_m3Type_i64: fprintf (stderr, "Result: %" PRIi64 "\n", *(i64*)valptrs[i]); break;
# if d_m3HasFloat
case c_m3Type_f32: fprintf (stderr, "Result: %" PRIf32 "\n", *(f32*)valptrs[i]); break;
case c_m3Type_f64: fprintf (stderr, "Result: %" PRIf64 "\n", *(f64*)valptrs[i]); break;
# endif
default: return "unknown return type";
}
}
@ -566,6 +576,10 @@ int main (int i_argc, const char* i_argv[])
const char* tmp = "65536";
ARGV_SET(tmp);
argStackSize = atol(tmp);
} else if (!strcmp("--gas-limit", arg)) {
const char* tmp = "0";
ARGV_SET(tmp);
initial_gas = current_gas = GAS_FACTOR * atol(tmp);
} else if (!strcmp("--dir", arg)) {
const char* argDir;
ARGV_SET(argDir);

@ -31,9 +31,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
if (result == 0) {
IM3Function f = NULL;
result = m3_FindFunction (&f, runtime, "fib");
/* TODO:
if (f) {
m3_CallV (f, 10);
}
}*/
} else {
m3_FreeModule (module);
}

@ -1073,7 +1073,7 @@ _ (PushConst (o, value, c_m3Type_i64)); m3log (compile,
}
#if d_m3HasFloat
#if d_m3ImplementFloat
M3Result Compile_Const_f32 (IM3Compilation o, m3opcode_t i_opcode)
{
M3Result result;
@ -2370,7 +2370,12 @@ const M3OpInfo c_operations [] =
# ifdef DEBUG // for codepage logging. the order doesn't matter:
# define d_m3DebugOp(OP) M3OP (#OP, 0, none, { op_##OP })
# if d_m3HasFloat
# define d_m3DebugTypedOp(OP) M3OP (#OP, 0, none, { op_##OP##_i32, op_##OP##_i64, op_##OP##_f32, op_##OP##_f64, })
# else
# define d_m3DebugTypedOp(OP) M3OP (#OP, 0, none, { op_##OP##_i32, op_##OP##_i64 })
# endif
d_m3DebugOp (Compile), d_m3DebugOp (Entry), d_m3DebugOp (End),
d_m3DebugOp (Unsupported), d_m3DebugOp (CallRawFunction),
@ -2383,11 +2388,13 @@ const M3OpInfo c_operations [] =
d_m3DebugOp (Select_i32_rss), d_m3DebugOp (Select_i32_srs), d_m3DebugOp (Select_i32_ssr), d_m3DebugOp (Select_i32_sss),
d_m3DebugOp (Select_i64_rss), d_m3DebugOp (Select_i64_srs), d_m3DebugOp (Select_i64_ssr), d_m3DebugOp (Select_i64_sss),
# if d_m3HasFloat
d_m3DebugOp (Select_f32_sss), d_m3DebugOp (Select_f32_srs), d_m3DebugOp (Select_f32_ssr),
d_m3DebugOp (Select_f32_rss), d_m3DebugOp (Select_f32_rrs), d_m3DebugOp (Select_f32_rsr),
d_m3DebugOp (Select_f64_sss), d_m3DebugOp (Select_f64_srs), d_m3DebugOp (Select_f64_ssr),
d_m3DebugOp (Select_f64_rss), d_m3DebugOp (Select_f64_rrs), d_m3DebugOp (Select_f64_rsr),
# endif
d_m3DebugTypedOp (SetGlobal), d_m3DebugOp (SetGlobal_s32), d_m3DebugOp (SetGlobal_s64),

@ -263,7 +263,7 @@ M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end)
else return m3Err_wasmUnderrun;
}
#if d_m3HasFloat || d_m3NoFloatDynamic
#if d_m3ImplementFloat
M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end)
{

@ -27,11 +27,9 @@
d_m3BeginExternC
#define d_m3ImplementFloat (d_m3HasFloat || d_m3NoFloatDynamic)
#if !defined(d_m3ShortTypesDefined)
#if d_m3HasFloat || d_m3NoFloatDynamic
typedef double f64;
typedef float f32;
#endif
typedef uint64_t u64;
typedef int64_t i64;
@ -41,6 +39,12 @@ typedef uint16_t u16;
typedef int16_t i16;
typedef uint8_t u8;
typedef int8_t i8;
#if d_m3ImplementFloat
typedef double f64;
typedef float f32;
#endif
#endif // d_m3ShortTypesDefined
#define PRIf32 "f"
@ -224,7 +228,7 @@ u32 SizeOfType (u8 i_m3Type);
M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
#if d_m3HasFloat || d_m3NoFloatDynamic
#if d_m3ImplementFloat
M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
#endif

@ -616,8 +616,10 @@ M3Result m3_GetGlobal (IM3Global i_global,
switch (i_global->type) {
case c_m3Type_i32: o_value->value.i32 = i_global->intValue; break;
case c_m3Type_i64: o_value->value.i64 = i_global->intValue; break;
# if d_m3HasFloat
case c_m3Type_f32: o_value->value.f32 = i_global->f32Value; break;
case c_m3Type_f64: o_value->value.f64 = i_global->f64Value; break;
# endif
default: return m3Err_invalidTypeId;
}
@ -636,8 +638,10 @@ M3Result m3_SetGlobal (IM3Global i_global,
switch (i_value->type) {
case c_m3Type_i32: i_global->intValue = i_value->value.i32; break;
case c_m3Type_i64: i_global->intValue = i_value->value.i64; break;
# if d_m3HasFloat
case c_m3Type_f32: i_global->f32Value = i_value->value.f32; break;
case c_m3Type_f64: i_global->f64Value = i_value->value.f64; break;
# endif
default: return m3Err_invalidTypeId;
}
@ -795,8 +799,10 @@ M3Result m3_CallVL (IM3Function i_function, va_list i_args)
switch (d_FuncArgType(ftype, i)) {
case c_m3Type_i32: *(i32*)(s) = va_arg(i_args, i32); s += 8; break;
case c_m3Type_i64: *(i64*)(s) = va_arg(i_args, i64); s += 8; break;
# if d_m3HasFloat
case c_m3Type_f32: *(f32*)(s) = va_arg(i_args, f64); s += 8; break; // f32 is passed as f64
case c_m3Type_f64: *(f64*)(s) = va_arg(i_args, f64); s += 8; break;
# endif
default: return "unknown argument type";
}
}
@ -836,8 +842,10 @@ M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argp
switch (d_FuncArgType(ftype, i)) {
case c_m3Type_i32: *(i32*)(s) = *(i32*)i_argptrs[i]; s += 8; break;
case c_m3Type_i64: *(i64*)(s) = *(i64*)i_argptrs[i]; s += 8; break;
# if d_m3HasFloat
case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; s += 8; break;
case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; s += 8; break;
# endif
default: return "unknown argument type";
}
}
@ -878,8 +886,10 @@ M3Result m3_CallArgv (IM3Function i_function, uint32_t i_argc, const char * i_
switch (d_FuncArgType(ftype, i)) {
case c_m3Type_i32: *(i32*)(s) = strtoul(i_argv[i], NULL, 10); s += 8; break;
case c_m3Type_i64: *(i64*)(s) = strtoull(i_argv[i], NULL, 10); s += 8; break;
case c_m3Type_f32: *(f32*)(s) = strtod(i_argv[i], NULL); s += 8; break; // strtof would be less portable
# if d_m3HasFloat
case c_m3Type_f32: *(f32*)(s) = strtod(i_argv[i], NULL); s += 8; break; // strtof would be less portable
case c_m3Type_f64: *(f64*)(s) = strtod(i_argv[i], NULL); s += 8; break;
# endif
default: return "unknown argument type";
}
}
@ -924,8 +934,10 @@ M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void *
switch (d_FuncRetType(ftype, i)) {
case c_m3Type_i32: *(i32*)o_retptrs[i] = *(i32*)(s); s += 8; break;
case c_m3Type_i64: *(i64*)o_retptrs[i] = *(i64*)(s); s += 8; break;
# if d_m3HasFloat
case c_m3Type_f32: *(f32*)o_retptrs[i] = *(f32*)(s); s += 8; break;
case c_m3Type_f64: *(f64*)o_retptrs[i] = *(f64*)(s); s += 8; break;
# endif
default: return "unknown return type";
}
}
@ -956,8 +968,10 @@ M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets)
switch (d_FuncRetType(ftype, i)) {
case c_m3Type_i32: *va_arg(o_rets, i32*) = *(i32*)(s); s += 8; break;
case c_m3Type_i64: *va_arg(o_rets, i64*) = *(i64*)(s); s += 8; break;
# if d_m3HasFloat
case c_m3Type_f32: *va_arg(o_rets, f32*) = *(f32*)(s); s += 8; break;
case c_m3Type_f64: *va_arg(o_rets, f64*) = *(f64*)(s); s += 8; break;
# endif
default: return "unknown argument type";
}
}
@ -1040,7 +1054,8 @@ M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module,
{
if (i_runtime)
{
i_runtime->error = (M3ErrorInfo){ i_result, i_runtime, i_module, i_function, i_file, i_lineNum };
i_runtime->error = (M3ErrorInfo){ .result = i_result, .runtime = i_runtime, .module = i_module,
.function = i_function, .file = i_file, .line = i_lineNum };
i_runtime->error.message = i_runtime->error_message;
va_list args;

@ -12,27 +12,35 @@
d_m3BeginExternC
#define m3MemData(mem) (u8*)(((M3MemoryHeader*)(mem))+1)
#define m3MemRuntime(mem) (((M3MemoryHeader*)(mem))->runtime)
#define m3MemInfo(mem) (&(((M3MemoryHeader*)(mem))->runtime->memory))
#if d_m3HasFloat
# define d_m3OpSig pc_t _pc, m3stack_t _sp, M3MemoryHeader * _mem, m3reg_t _r0, f64 _fp0
# define d_m3OpArgs _sp, _mem, _r0, _fp0
# define d_m3OpAllArgs _pc, _sp, _mem, _r0, _fp0
# define d_m3OpDefaultArgs 0, 0.0
# define d_m3ClearRegisters _r0 = 0; _fp0 = 0.0;
#else
# define d_m3OpSig pc_t _pc, m3stack_t _sp, M3MemoryHeader * _mem, m3reg_t _r0
# define d_m3OpArgs _sp, _mem, _r0
# define d_m3OpAllArgs _pc, _sp, _mem, _r0
# define d_m3OpDefaultArgs 0
# define d_m3ClearRegisters _r0 = 0;
#endif
# define m3MemData(mem) (u8*)(((M3MemoryHeader*)(mem))+1)
# define m3MemRuntime(mem) (((M3MemoryHeader*)(mem))->runtime)
# define m3MemInfo(mem) (&(((M3MemoryHeader*)(mem))->runtime->memory))
# define d_m3BaseOpSig pc_t _pc, m3stack_t _sp, M3MemoryHeader * _mem, m3reg_t _r0
# define d_m3BaseOpArgs _sp, _mem, _r0
# define d_m3BaseOpAllArgs _pc, _sp, _mem, _r0
# define d_m3BaseOpDefaultArgs 0
# define d_m3BaseClearRegisters _r0 = 0;
# define d_m3ExpOpSig(...) d_m3BaseOpSig, __VA_ARGS__
# define d_m3ExpOpArgs(...) d_m3BaseOpArgs, __VA_ARGS__
# define d_m3ExpOpAllArgs(...) d_m3BaseOpAllArgs, __VA_ARGS__
# define d_m3ExpOpDefaultArgs(...) d_m3BaseOpDefaultArgs, __VA_ARGS__
# define d_m3ExpClearRegisters(...) d_m3BaseClearRegisters; __VA_ARGS__
# if d_m3HasFloat
# define d_m3OpSig d_m3ExpOpSig (f64 _fp0)
# define d_m3OpArgs d_m3ExpOpArgs (_fp0)
# define d_m3OpAllArgs d_m3ExpOpAllArgs (_fp0)
# define d_m3OpDefaultArgs d_m3ExpOpDefaultArgs (0.)
# define d_m3ClearRegisters d_m3ExpClearRegisters (_fp0 = 0.;)
# else
# define d_m3OpSig d_m3BaseOpSig
# define d_m3OpArgs d_m3BaseOpArgs
# define d_m3OpAllArgs d_m3BaseOpAllArgs
# define d_m3OpDefaultArgs d_m3BaseOpDefaultArgs
# define d_m3ClearRegisters d_m3BaseClearRegisters
# endif
typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig);

@ -291,7 +291,7 @@ M3Result Parse_InitExpr (M3Module * io_module, bytes_t * io_bytes, cbytes_t i_
#else
M3Compilation compilation;
#endif
compilation = (M3Compilation){ NULL, io_module, * io_bytes, i_end };
compilation = (M3Compilation){ .runtime = NULL, .module = io_module, .wasm = * io_bytes, .wasmEnd = i_end };
result = CompileBlockStatements (& compilation);

Loading…
Cancel
Save