From 771dae7feb341bfc14f5f1a6582b3463d0230476 Mon Sep 17 00:00:00 2001 From: Steve Akinyemi Date: Tue, 20 Nov 2018 20:11:58 +0100 Subject: [PATCH] Refactor api code and doc --- Cargo.lock | 42 +- Cargo.toml | 16 +- cranelift | 1 + examples/em_abort.wat | 31 + examples/em_exit.wat | 27 + examples/em_printf.wat | 1751 ----------------- examples/em_read_file.wat | 43 + src/apis/emscripten/README.md | 394 ++++ .../printf.rs => apis/emscripten/io.rs} | 4 + src/apis/emscripten/memory.rs | 25 + src/{linkers => apis}/emscripten/mod.rs | 33 +- src/apis/emscripten/process.rs | 39 + .../emscripten/tests/printf.wast | 0 .../emscripten/tests/putchar.wast | 0 src/apis/gcc/.gitignore | 0 src/apis/host/mod.rs | 4 + src/apis/host/posix/mod.rs | 3 + src/apis/host/posix/syscalls.rs | 37 + src/apis/llvm/.gitignore | 0 src/{linkers => apis}/mod.rs | 2 + src/linkers/emscripten/README.md | 389 ---- src/linkers/emscripten/abort.rs | 7 - src/linkers/emscripten/putchar.rs | 1 - src/linkers/emscripten/syscalls/darwin/mod.rs | 1 - .../emscripten/syscalls/darwin/syscalls.rs | 25 - src/linkers/emscripten/syscalls/mod.rs | 3 - src/main.rs | 6 +- src/spectests/_common.rs | 2 +- src/webassembly/import_object.rs | 2 +- src/webassembly/instance.rs | 175 +- src/webassembly/memory.rs | 5 + src/webassembly/module.rs | 60 +- 32 files changed, 796 insertions(+), 2332 deletions(-) create mode 160000 cranelift create mode 100644 examples/em_abort.wat create mode 100644 examples/em_exit.wat delete mode 100644 examples/em_printf.wat create mode 100644 examples/em_read_file.wat create mode 100644 src/apis/emscripten/README.md rename src/{linkers/emscripten/printf.rs => apis/emscripten/io.rs} (88%) create mode 100644 src/apis/emscripten/memory.rs rename src/{linkers => apis}/emscripten/mod.rs (53%) create mode 100644 src/apis/emscripten/process.rs rename src/{linkers => apis}/emscripten/tests/printf.wast (100%) rename src/{linkers => apis}/emscripten/tests/putchar.wast (100%) create mode 100644 src/apis/gcc/.gitignore create mode 100644 src/apis/host/mod.rs create mode 100644 src/apis/host/posix/mod.rs create mode 100644 src/apis/host/posix/syscalls.rs create mode 100644 src/apis/llvm/.gitignore rename src/{linkers => apis}/mod.rs (82%) delete mode 100644 src/linkers/emscripten/README.md delete mode 100644 src/linkers/emscripten/abort.rs delete mode 100644 src/linkers/emscripten/putchar.rs delete mode 100644 src/linkers/emscripten/syscalls/darwin/mod.rs delete mode 100644 src/linkers/emscripten/syscalls/darwin/syscalls.rs delete mode 100644 src/linkers/emscripten/syscalls/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 8e6da6342..51d7645f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,19 +85,17 @@ dependencies = [ [[package]] name = "cranelift-bforest" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.23.0", ] [[package]] name = "cranelift-codegen" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-bforest 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-codegen-meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-bforest 0.23.0", + "cranelift-codegen-meta 0.23.0", + "cranelift-entity 0.23.0", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -107,22 +105,19 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.23.0", ] [[package]] name = "cranelift-entity" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cranelift-frontend" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.23.0", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -130,9 +125,8 @@ dependencies = [ [[package]] name = "cranelift-native" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.23.0", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -140,11 +134,10 @@ dependencies = [ [[package]] name = "cranelift-wasm" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-frontend 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.23.0", + "cranelift-entity 0.23.0", + "cranelift-frontend 0.23.0", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -594,10 +587,10 @@ dependencies = [ name = "wasmer" version = "0.1.0" dependencies = [ - "cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-native 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.23.0", + "cranelift-entity 0.23.0", + "cranelift-native 0.23.0", + "cranelift-wasm 0.23.0", "docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (git+https://github.com/rust-lang/libc)", @@ -654,13 +647,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" -"checksum cranelift-bforest 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5f8e1ab4f73b59a98531a8013d8ed3ca7edb4e36984cb301d9c06f6892787b" -"checksum cranelift-codegen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437ec8212686e6cdacfea75aaedb4ab8b013869be1e8693a4cb97a60f135035" -"checksum cranelift-codegen-meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4eac16097b96e9f609df735555f2d1658531750fbc3805bca1daca7671aef9eb" -"checksum cranelift-entity 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9be3f82369346201c2e0cff720522e6eb55459e51c916b2199f25cff2058ca96" -"checksum cranelift-frontend 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5d18ab2bc89a09b4275442a9559dc0f947b9a8ad9ae9ee89452a057df54ced" -"checksum cranelift-native 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d8d3b5951eefd89778dc59b0e33b556573a870538bc21982019bd4c4003b0a2d" -"checksum cranelift-wasm 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5906a111814d43d84002ef974eb0c023804fd4d1866b34f43c1bb588a759ad8" "checksum docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c92df70dfaaabecc14b409fd79f55ba0f247780529db1d73bfa601e1d3ac0" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" diff --git a/Cargo.toml b/Cargo.toml index 3c795b0aa..1e11d8f45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,14 +20,14 @@ include = [ ] [dependencies] -cranelift-native = "0.23.0" -# cranelift-native = { path = "cranelift/lib/native" } -cranelift-codegen = "0.23.0" -# cranelift-codegen = { path = "cranelift/lib/codegen" } -cranelift-entity = "0.23.0" -# cranelift-entity = { path = "cranelift/lib/entity" } -cranelift-wasm = "0.23.0" -# cranelift-wasm = { path = "cranelift/lib/wasm" } +# cranelift-native = "0.23.0" +cranelift-native = { path = "cranelift/lib/native" } +# cranelift-codegen = "0.23.0" +cranelift-codegen = { path = "cranelift/lib/codegen" } +# cranelift-entity = "0.23.0" +cranelift-entity = { path = "cranelift/lib/entity" } +# cranelift-wasm = "0.23.0" +cranelift-wasm = { path = "cranelift/lib/wasm" } docopt = "1.0.0" serde = "1.0.55" serde_derive = "1.0.55" diff --git a/cranelift b/cranelift new file mode 160000 index 000000000..3f6fdf952 --- /dev/null +++ b/cranelift @@ -0,0 +1 @@ +Subproject commit 3f6fdf952c5fe52381e8c16f5d1912972fc2d394 diff --git a/examples/em_abort.wat b/examples/em_abort.wat new file mode 100644 index 000000000..1eb282754 --- /dev/null +++ b/examples/em_abort.wat @@ -0,0 +1,31 @@ +(module + (type $t1 (func (param i32 i32) (result i32))) + (type $t2 (func (param i32))) + (type $t3 (func )) + (func $printf (import "env" "printf") (type $t1)) + (func $abort (import "env" "abort") (type $t2)) + (func $_abort (import "env" "_abort") (type $t3)) + (func $abort_on_cannot_grow_memory (import "env" "abortOnCannotGrowMemory") (type $t3)) + (memory 1) + (data (i32.const 0) ">>> First\00") + (data (i32.const 24) ">>> Second\00") + (data (i32.const 48) "Aborting abruptly!\00") + (func $main (export "main") + ;; print ">>> First" + (call $printf (i32.const 0) (i32.const 0)) + (drop) + + ;; aborts + (call $_abort) ;; () + + ;; aborts + (call $abort_on_cannot_grow_memory) ;; () + + ;; aborts + (call $abort (i32.const 48)) ;; (message: u32) + + ;; print ">>> Second" + (call $printf (i32.const 24) (i32.const 0)) + (drop) + ) +) diff --git a/examples/em_exit.wat b/examples/em_exit.wat new file mode 100644 index 000000000..507985f35 --- /dev/null +++ b/examples/em_exit.wat @@ -0,0 +1,27 @@ +(module + (type $t1 (func (param i32))) + (func $putchar (import "env" "putchar") (type $t1)) + (func $sys_exit (import "env" "___syscall1") (type $t1)) + (memory 1) + (func $main (export "main") + ;; print "Hello" + (call $putchar (i32.const 72)) + (call $putchar (i32.const 101)) + (call $putchar (i32.const 108)) + (call $putchar (i32.const 108)) + (call $putchar (i32.const 111)) + (call $putchar (i32.const 32)) + + ;; exit abruptly + (call $sys_exit (i32.const 255)) ;; (status: c_int) -> c_int + + ;; print " World!" + (call $putchar (i32.const 87)) + (call $putchar (i32.const 111)) + (call $putchar (i32.const 114)) + (call $putchar (i32.const 108)) + (call $putchar (i32.const 100)) + (call $putchar (i32.const 33)) + (call $putchar (i32.const 10)) + ) +) diff --git a/examples/em_printf.wat b/examples/em_printf.wat deleted file mode 100644 index 7044b9c33..000000000 --- a/examples/em_printf.wat +++ /dev/null @@ -1,1751 +0,0 @@ -(module - (type $t0 (func (param i32 i32 i32) (result i32))) - (type $t1 (func (param i32 i32 i32 i32) (result i32))) - (type $t2 (func (param i32 i32) (result i32))) - (type $t3 (func (param i32 i32 i32 i32 i32 i32) (result i32))) - (type $t4 (func (result i32))) - (type $t5 (func (param i32) (result i32))) - (type $t6 (func (param i32))) - (type $t7 (func (param i32 i64 i32) (result i64))) - (import "env" "__syscall3" (func $env.__syscall3 (type $t1))) - (import "env" "__syscall1" (func $env.__syscall1 (type $t2))) - (import "env" "__syscall5" (func $env.__syscall5 (type $t3))) - (func $main (export "main") (type $t4) (result i32) - i32.const 1024 - call $f9 - drop - i32.const 0) - (func $f4 (type $t5) (param $p0 i32) (result i32) - (local $l0 i32) (local $l1 i32) - get_local $p0 - i32.load offset=76 - i32.const -1073741825 - i32.and - i32.const 27 - i32.load - tee_local $l1 - i32.ne - if $I0 - get_local $p0 - i32.const 76 - i32.add - set_local $p0 - block $B1 - loop $L2 - get_local $p0 - i32.load - tee_local $l0 - i32.eqz - br_if $B1 - get_local $p0 - i32.load - get_local $l0 - i32.ne - br_if $L2 - end - get_local $p0 - get_local $l0 - i32.const 1073741824 - i32.or - i32.store - get_local $p0 - i32.load - tee_local $l0 - if $I3 - loop $L4 - i32.const 240 - get_local $p0 - i32.const 128 - get_local $l0 - call $env.__syscall3 - i32.const -38 - i32.eq - if $I5 - i32.const 240 - get_local $p0 - i32.const 0 - get_local $l0 - call $env.__syscall3 - drop - end - get_local $p0 - i32.load - tee_local $l0 - br_if $L4 - end - end - get_local $l1 - i32.const 1073741824 - i32.or - set_local $l1 - end - get_local $p0 - get_local $l1 - i32.store - i32.const 1 - set_local $l0 - end - get_local $l0) - (func $f5 (type $t6) (param $p0 i32) - (local $l0 i32) - get_local $p0 - i32.const 76 - i32.add - set_local $p0 - loop $L0 - get_local $p0 - i32.load - tee_local $l0 - get_local $p0 - i32.load - i32.ne - br_if $L0 - end - get_local $p0 - i32.const 0 - i32.store - block $B1 - get_local $l0 - i32.const 1073741824 - i32.and - i32.eqz - br_if $B1 - i32.const 240 - get_local $p0 - i32.const 129 - i32.const 1 - call $env.__syscall3 - i32.const -38 - i32.ne - br_if $B1 - i32.const 240 - get_local $p0 - i32.const 1 - i32.const 1 - call $env.__syscall3 - drop - end) - (func $f6 (type $t5) (param $p0 i32) (result i32) - (local $l0 i32) - get_local $p0 - get_local $p0 - i32.load8_u offset=74 - tee_local $l0 - i32.const -1 - i32.add - get_local $l0 - i32.or - i32.store8 offset=74 - get_local $p0 - i32.load - tee_local $l0 - i32.const 8 - i32.and - i32.eqz - if $I0 - get_local $p0 - i64.const 0 - i64.store offset=4 align=4 - get_local $p0 - get_local $p0 - i32.load offset=44 - tee_local $l0 - i32.store offset=28 - get_local $p0 - get_local $l0 - i32.store offset=20 - get_local $p0 - get_local $l0 - get_local $p0 - i32.load offset=48 - i32.add - i32.store offset=16 - i32.const 0 - return - end - get_local $p0 - get_local $l0 - i32.const 32 - i32.or - i32.store - i32.const -1) - (func $f7 (type $t1) (param $p0 i32) (param $p1 i32) (param $p2 i32) (param $p3 i32) (result i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) - get_local $p3 - i32.load offset=76 - i32.const 0 - i32.ge_s - if $I0 - get_local $p3 - call $f4 - i32.const 0 - i32.ne - set_local $l3 - end - get_local $p2 - get_local $p1 - i32.mul - set_local $l1 - block $B1 - block $B2 - block $B3 - block $B4 - block $B5 - get_local $p3 - i32.load offset=16 - tee_local $l0 - if $I6 - get_local $l0 - get_local $p3 - i32.load offset=20 - tee_local $l4 - i32.sub - get_local $l1 - i32.ge_u - br_if $B5 - br $B3 - end - i32.const 0 - set_local $l0 - get_local $p3 - call $f6 - br_if $B2 - get_local $p3 - i32.const 16 - i32.add - i32.load - get_local $p3 - i32.load offset=20 - tee_local $l4 - i32.sub - get_local $l1 - i32.lt_u - br_if $B3 - end - block $B7 (result i32) - block $B8 - get_local $p3 - i32.load8_s offset=75 - i32.const 0 - i32.lt_s - br_if $B8 - get_local $p0 - get_local $l1 - i32.add - set_local $l7 - i32.const 0 - set_local $l0 - loop $L9 - get_local $l1 - get_local $l0 - i32.add - i32.eqz - br_if $B8 - get_local $l7 - get_local $l0 - i32.add - set_local $l5 - get_local $l0 - i32.const -1 - i32.add - tee_local $l6 - set_local $l0 - get_local $l5 - i32.const -1 - i32.add - i32.load8_u - i32.const 10 - i32.ne - br_if $L9 - end - get_local $p3 - get_local $p0 - get_local $l1 - get_local $l6 - i32.add - i32.const 1 - i32.add - tee_local $l2 - get_local $p3 - i32.load offset=36 - call_indirect (type $t0) - tee_local $l0 - get_local $l2 - i32.lt_u - br_if $B2 - get_local $l7 - get_local $l6 - i32.add - i32.const 1 - i32.add - set_local $p0 - get_local $p3 - i32.const 20 - i32.add - i32.load - set_local $l4 - get_local $l6 - i32.const -1 - i32.xor - br $B7 - end - get_local $l1 - end - set_local $l0 - get_local $l4 - get_local $p0 - get_local $l0 - call $f15 - drop - get_local $p3 - i32.const 20 - i32.add - tee_local $l5 - get_local $l5 - i32.load - get_local $l0 - i32.add - i32.store - get_local $l2 - get_local $l0 - i32.add - set_local $l0 - end - br $B2 - end - get_local $p3 - get_local $p0 - get_local $l1 - get_local $p3 - i32.load offset=36 - call_indirect (type $t0) - set_local $l0 - end - get_local $l3 - i32.eqz - br_if $B1 - get_local $p3 - call $f5 - end - get_local $l0 - get_local $l1 - i32.eq - if $I10 - get_local $p2 - i32.const 0 - get_local $p1 - select - return - end - get_local $l0 - get_local $p1 - i32.div_u) - (func $f8 (type $t2) (param $p0 i32) (param $p1 i32) (result i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) - get_global $g0 - i32.const 16 - i32.sub - tee_local $l1 - set_global $g0 - get_local $l1 - get_local $p1 - i32.store8 offset=15 - block $B0 (result i32) - block $B1 - block $B2 - get_local $p0 - i32.load offset=16 - tee_local $l0 - if $I3 - get_local $p0 - i32.load offset=20 - tee_local $l2 - get_local $l0 - i32.ge_u - br_if $B1 - br $B2 - end - i32.const -1 - tee_local $l0 - get_local $p0 - call $f6 - br_if $B0 - drop - get_local $p0 - i32.load offset=20 - tee_local $l2 - get_local $p0 - i32.const 16 - i32.add - i32.load - i32.ge_u - br_if $B1 - end - get_local $p1 - i32.const 255 - i32.and - tee_local $l0 - get_local $p0 - i32.load8_s offset=75 - i32.eq - br_if $B1 - get_local $p0 - i32.const 20 - i32.add - get_local $l2 - i32.const 1 - i32.add - i32.store - get_local $l2 - get_local $p1 - i32.store8 - get_local $l1 - i32.const 16 - i32.add - set_global $g0 - get_local $l0 - return - end - i32.const -1 - tee_local $l0 - get_local $p0 - get_local $l1 - i32.const 15 - i32.add - i32.const 1 - get_local $p0 - i32.load offset=36 - call_indirect (type $t0) - i32.const 1 - i32.ne - br_if $B0 - drop - get_local $l1 - i32.load8_u offset=15 - end - set_local $l0 - get_local $l1 - i32.const 16 - i32.add - set_global $g0 - get_local $l0) - (func $f9 (type $t5) (param $p0 i32) (result i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) - i32.const 1036 - i32.load - tee_local $l0 - i32.load offset=76 - i32.const 0 - i32.ge_s - if $I0 - get_local $l0 - call $f4 - set_local $l1 - end - block $B1 - block $B2 - i32.const -1 - i32.const 0 - get_local $p0 - call $f16 - tee_local $l2 - get_local $p0 - i32.const 1 - get_local $l2 - get_local $l0 - call $f7 - i32.ne - select - i32.const 0 - i32.ge_s - if $I3 - block $B4 - get_local $l0 - i32.load8_u offset=75 - i32.const 10 - i32.eq - br_if $B4 - get_local $l0 - i32.load offset=20 - tee_local $p0 - get_local $l0 - i32.load offset=16 - i32.ge_u - br_if $B4 - get_local $l0 - i32.const 20 - i32.add - get_local $p0 - i32.const 1 - i32.add - i32.store - get_local $p0 - i32.const 10 - i32.store8 - i32.const 0 - set_local $p0 - get_local $l1 - br_if $B2 - br $B1 - end - get_local $l0 - i32.const 10 - call $f8 - i32.const 31 - i32.shr_s - set_local $p0 - get_local $l1 - i32.eqz - br_if $B1 - br $B2 - end - i32.const -1 - set_local $p0 - get_local $l1 - i32.eqz - br_if $B1 - end - get_local $l0 - call $f5 - end - get_local $p0) - (func $f10 (type $t5) (param $p0 i32) (result i32) - get_local $p0 - i32.const -4095 - i32.ge_u - if $I0 - i32.const 31 - i32.const 0 - get_local $p0 - i32.sub - i32.store - i32.const -1 - set_local $p0 - end - get_local $p0) - (func $f11 (type $t5) (param $p0 i32) (result i32) - i32.const 6 - get_local $p0 - i32.load offset=60 - call $env.__syscall1 - call $f10) - (func $f12 (type $t0) (param $p0 i32) (param $p1 i32) (param $p2 i32) (result i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) - get_global $g0 - i32.const 16 - i32.sub - tee_local $l0 - set_global $g0 - get_local $l0 - get_local $p1 - i32.store offset=8 - get_local $l0 - get_local $p2 - i32.store offset=12 - get_local $l0 - get_local $p0 - i32.load offset=28 - tee_local $p1 - i32.store - get_local $l0 - get_local $p0 - i32.load offset=20 - get_local $p1 - i32.sub - tee_local $p1 - i32.store offset=4 - i32.const 2 - set_local $l3 - block $B0 - block $B1 - get_local $p1 - get_local $p2 - i32.add - tee_local $l4 - i32.const 146 - get_local $p0 - i32.load offset=60 - get_local $l0 - i32.const 2 - call $env.__syscall3 - call $f10 - tee_local $l1 - i32.ne - if $I2 - get_local $l0 - set_local $p1 - get_local $p0 - i32.const 60 - i32.add - set_local $l6 - loop $L3 - get_local $l1 - i32.const -1 - i32.le_s - br_if $B1 - get_local $p1 - i32.const 8 - i32.add - get_local $p1 - get_local $l1 - get_local $p1 - i32.load offset=4 - tee_local $l5 - i32.gt_u - tee_local $l2 - select - tee_local $p1 - get_local $p1 - i32.load - get_local $l1 - get_local $l5 - i32.const 0 - get_local $l2 - select - i32.sub - tee_local $l5 - i32.add - i32.store - get_local $p1 - get_local $p1 - i32.load offset=4 - get_local $l5 - i32.sub - i32.store offset=4 - get_local $l4 - get_local $l1 - i32.sub - set_local $l4 - i32.const 146 - get_local $l6 - i32.load - get_local $p1 - get_local $l3 - get_local $l2 - i32.sub - tee_local $l3 - call $env.__syscall3 - call $f10 - tee_local $l2 - set_local $l1 - get_local $l4 - get_local $l2 - i32.ne - br_if $L3 - end - end - get_local $p0 - i32.const 28 - i32.add - get_local $p0 - i32.load offset=44 - tee_local $p1 - i32.store - get_local $p0 - i32.const 20 - i32.add - get_local $p1 - i32.store - get_local $p0 - get_local $p1 - get_local $p0 - i32.load offset=48 - i32.add - i32.store offset=16 - get_local $p2 - set_local $l1 - br $B0 - end - get_local $p0 - i64.const 0 - i64.store offset=16 - i32.const 0 - set_local $l1 - get_local $p0 - i32.const 28 - i32.add - i32.const 0 - i32.store - get_local $p0 - get_local $p0 - i32.load - i32.const 32 - i32.or - i32.store - get_local $l3 - i32.const 2 - i32.eq - br_if $B0 - get_local $p1 - i32.load offset=4 - set_local $p1 - get_local $l0 - i32.const 16 - i32.add - set_global $g0 - get_local $p2 - get_local $p1 - i32.sub - return - end - get_local $l0 - i32.const 16 - i32.add - set_global $g0 - get_local $l1) - (func $f13 (type $t0) (param $p0 i32) (param $p1 i32) (param $p2 i32) (result i32) - (local $l0 i32) - get_global $g0 - i32.const 16 - i32.sub - tee_local $l0 - set_global $g0 - get_local $p0 - i32.const 1 - i32.store offset=36 - block $B0 - get_local $p0 - i32.load8_u - i32.const 64 - i32.and - br_if $B0 - i32.const 54 - get_local $p0 - i32.load offset=60 - i32.const 21523 - get_local $l0 - i32.const 8 - i32.add - call $env.__syscall3 - i32.eqz - br_if $B0 - get_local $p0 - i32.const 255 - i32.store8 offset=75 - end - get_local $p0 - get_local $p1 - get_local $p2 - call $f12 - set_local $p0 - get_local $l0 - i32.const 16 - i32.add - set_global $g0 - get_local $p0) - (func $f14 (type $t7) (param $p0 i32) (param $p1 i64) (param $p2 i32) (result i64) - (local $l0 i32) - get_global $g0 - i32.const 16 - i32.sub - tee_local $l0 - set_global $g0 - i32.const 140 - get_local $p0 - i32.load offset=60 - get_local $p1 - i64.const 32 - i64.shr_u - i32.wrap/i64 - get_local $p1 - i32.wrap/i64 - get_local $l0 - i32.const 8 - i32.add - get_local $p2 - call $env.__syscall5 - call $f10 - i32.const 0 - i32.ge_s - if $I0 - get_local $l0 - i64.load offset=8 - set_local $p1 - get_local $l0 - i32.const 16 - i32.add - set_global $g0 - get_local $p1 - return - end - get_local $l0 - i64.const -1 - i64.store offset=8 - get_local $l0 - i32.const 16 - i32.add - set_global $g0 - i64.const -1) - (func $f15 (type $t0) (param $p0 i32) (param $p1 i32) (param $p2 i32) (result i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) - block $B0 - block $B1 - block $B2 - get_local $p2 - i32.eqz - get_local $p1 - i32.const 3 - i32.and - i32.eqz - i32.or - i32.eqz - if $I3 - get_local $p0 - set_local $l0 - block $B4 - loop $L5 - get_local $l0 - get_local $p1 - i32.load8_u - i32.store8 - get_local $p2 - i32.const -1 - i32.add - set_local $l1 - get_local $l0 - i32.const 1 - i32.add - set_local $l0 - get_local $p1 - i32.const 1 - i32.add - set_local $p1 - get_local $p2 - i32.const 1 - i32.eq - br_if $B4 - get_local $l1 - set_local $p2 - get_local $p1 - i32.const 3 - i32.and - br_if $L5 - end - end - get_local $l0 - i32.const 3 - i32.and - i32.eqz - br_if $B2 - br $B1 - end - get_local $p2 - set_local $l1 - get_local $p0 - tee_local $l0 - i32.const 3 - i32.and - br_if $B1 - end - block $B6 - block $B7 - get_local $l1 - i32.const 16 - i32.ge_u - if $I8 - get_local $l0 - get_local $l1 - i32.const -16 - i32.add - tee_local $l3 - i32.const -16 - i32.and - tee_local $l4 - i32.const 16 - i32.add - tee_local $l5 - i32.add - set_local $l2 - get_local $p1 - set_local $p2 - loop $L9 - get_local $l0 - get_local $p2 - i32.load - i32.store - get_local $l0 - i32.const 4 - i32.add - get_local $p2 - i32.const 4 - i32.add - i32.load - i32.store - get_local $l0 - i32.const 8 - i32.add - get_local $p2 - i32.const 8 - i32.add - i32.load - i32.store - get_local $l0 - i32.const 12 - i32.add - get_local $p2 - i32.const 12 - i32.add - i32.load - i32.store - get_local $l0 - i32.const 16 - i32.add - set_local $l0 - get_local $p2 - i32.const 16 - i32.add - set_local $p2 - get_local $l1 - i32.const -16 - i32.add - tee_local $l1 - i32.const 15 - i32.gt_u - br_if $L9 - end - get_local $p1 - get_local $l5 - i32.add - set_local $p1 - i32.const 8 - set_local $l0 - get_local $l3 - get_local $l4 - i32.sub - tee_local $l1 - i32.const 8 - i32.and - br_if $B7 - br $B6 - end - get_local $l0 - set_local $l2 - i32.const 8 - set_local $l0 - get_local $l1 - i32.const 8 - i32.and - i32.eqz - br_if $B6 - end - get_local $l2 - get_local $p1 - i32.load - i32.store - get_local $l2 - get_local $p1 - i32.load offset=4 - i32.store offset=4 - get_local $p1 - get_local $l0 - i32.add - set_local $p1 - get_local $l2 - get_local $l0 - i32.add - set_local $l2 - end - block $B10 - block $B11 - block $B12 - get_local $l1 - i32.const 4 - i32.and - i32.eqz - if $I13 - i32.const 2 - set_local $l0 - get_local $l1 - i32.const 2 - i32.and - br_if $B12 - br $B11 - end - get_local $l2 - get_local $p1 - i32.load - i32.store - get_local $p1 - i32.const 4 - i32.add - set_local $p1 - get_local $l2 - i32.const 4 - i32.add - set_local $l2 - i32.const 2 - set_local $l0 - get_local $l1 - i32.const 2 - i32.and - i32.eqz - br_if $B11 - end - get_local $l2 - get_local $p1 - i32.load8_u - i32.store8 - get_local $l2 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $l2 - get_local $l0 - i32.add - set_local $l2 - get_local $p1 - get_local $l0 - i32.add - set_local $p1 - get_local $l1 - i32.const 1 - i32.and - br_if $B10 - br $B0 - end - get_local $l1 - i32.const 1 - i32.and - i32.eqz - br_if $B0 - end - get_local $l2 - get_local $p1 - i32.load8_u - i32.store8 - get_local $p0 - return - end - block $B14 - block $B15 - block $B16 - block $B17 - block $B18 - block $B19 - block $B20 - block $B21 - block $B22 - block $B23 - block $B24 - block $B25 - get_local $l1 - i32.const 32 - i32.lt_u - br_if $B25 - get_local $l0 - i32.const 3 - i32.and - tee_local $p2 - i32.const 3 - i32.eq - br_if $B24 - get_local $p2 - i32.const 2 - i32.eq - br_if $B23 - get_local $p2 - i32.const 1 - i32.ne - br_if $B25 - get_local $l0 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $l0 - get_local $p1 - i32.load - tee_local $l3 - i32.store8 - get_local $l0 - get_local $p1 - i32.load8_u offset=2 - i32.store8 offset=2 - get_local $p1 - i32.const 16 - i32.add - set_local $p2 - get_local $l1 - i32.const -19 - i32.add - set_local $l5 - get_local $l1 - i32.const -3 - i32.add - set_local $l4 - get_local $l0 - i32.const 3 - i32.add - set_local $l2 - get_local $p1 - get_local $l1 - i32.const -20 - i32.add - i32.const -16 - i32.and - tee_local $l6 - i32.const 19 - i32.add - tee_local $l7 - i32.add - set_local $p1 - loop $L26 - get_local $l2 - get_local $p2 - i32.const -12 - i32.add - i32.load - tee_local $l1 - i32.const 8 - i32.shl - get_local $l3 - i32.const 24 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 4 - i32.add - get_local $p2 - i32.const -8 - i32.add - i32.load - tee_local $l3 - i32.const 8 - i32.shl - get_local $l1 - i32.const 24 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 8 - i32.add - get_local $p2 - i32.const -4 - i32.add - i32.load - tee_local $l1 - i32.const 8 - i32.shl - get_local $l3 - i32.const 24 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 12 - i32.add - get_local $p2 - i32.load - tee_local $l3 - i32.const 8 - i32.shl - get_local $l1 - i32.const 24 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 16 - i32.add - set_local $l2 - get_local $p2 - i32.const 16 - i32.add - set_local $p2 - get_local $l4 - i32.const -16 - i32.add - tee_local $l4 - i32.const 16 - i32.gt_u - br_if $L26 - end - get_local $l5 - get_local $l6 - i32.sub - set_local $l1 - get_local $l0 - get_local $l7 - i32.add - set_local $l0 - end - i32.const 16 - set_local $p2 - get_local $l1 - i32.const 16 - i32.and - br_if $B22 - br $B21 - end - get_local $l0 - get_local $p1 - i32.load - tee_local $l3 - i32.store8 - get_local $p1 - i32.const 16 - i32.add - set_local $p2 - get_local $l1 - i32.const -17 - i32.add - set_local $l5 - get_local $l1 - i32.const -1 - i32.add - set_local $l4 - get_local $l0 - i32.const 1 - i32.add - set_local $l2 - get_local $p1 - get_local $l1 - i32.const -20 - i32.add - i32.const -16 - i32.and - tee_local $l6 - i32.const 17 - i32.add - tee_local $l7 - i32.add - set_local $p1 - loop $L27 - get_local $l2 - get_local $p2 - i32.const -12 - i32.add - i32.load - tee_local $l1 - i32.const 24 - i32.shl - get_local $l3 - i32.const 8 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 4 - i32.add - get_local $p2 - i32.const -8 - i32.add - i32.load - tee_local $l3 - i32.const 24 - i32.shl - get_local $l1 - i32.const 8 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 8 - i32.add - get_local $p2 - i32.const -4 - i32.add - i32.load - tee_local $l1 - i32.const 24 - i32.shl - get_local $l3 - i32.const 8 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 12 - i32.add - get_local $p2 - i32.load - tee_local $l3 - i32.const 24 - i32.shl - get_local $l1 - i32.const 8 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 16 - i32.add - set_local $l2 - get_local $p2 - i32.const 16 - i32.add - set_local $p2 - get_local $l4 - i32.const -16 - i32.add - tee_local $l4 - i32.const 18 - i32.gt_u - br_if $L27 - end - get_local $l0 - get_local $l7 - i32.add - set_local $l0 - i32.const 16 - set_local $p2 - get_local $l5 - get_local $l6 - i32.sub - tee_local $l1 - i32.const 16 - i32.and - i32.eqz - br_if $B21 - br $B22 - end - get_local $l0 - get_local $p1 - i32.load - tee_local $l3 - i32.store8 - get_local $l0 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $p1 - i32.const 16 - i32.add - set_local $p2 - get_local $l1 - i32.const -18 - i32.add - set_local $l5 - get_local $l1 - i32.const -2 - i32.add - set_local $l4 - get_local $l0 - i32.const 2 - i32.add - set_local $l2 - get_local $p1 - get_local $l1 - i32.const -20 - i32.add - i32.const -16 - i32.and - tee_local $l6 - i32.const 18 - i32.add - tee_local $l7 - i32.add - set_local $p1 - loop $L28 - get_local $l2 - get_local $p2 - i32.const -12 - i32.add - i32.load - tee_local $l1 - i32.const 16 - i32.shl - get_local $l3 - i32.const 16 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 4 - i32.add - get_local $p2 - i32.const -8 - i32.add - i32.load - tee_local $l3 - i32.const 16 - i32.shl - get_local $l1 - i32.const 16 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 8 - i32.add - get_local $p2 - i32.const -4 - i32.add - i32.load - tee_local $l1 - i32.const 16 - i32.shl - get_local $l3 - i32.const 16 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 12 - i32.add - get_local $p2 - i32.load - tee_local $l3 - i32.const 16 - i32.shl - get_local $l1 - i32.const 16 - i32.shr_u - i32.or - i32.store - get_local $l2 - i32.const 16 - i32.add - set_local $l2 - get_local $p2 - i32.const 16 - i32.add - set_local $p2 - get_local $l4 - i32.const -16 - i32.add - tee_local $l4 - i32.const 17 - i32.gt_u - br_if $L28 - end - get_local $l0 - get_local $l7 - i32.add - set_local $l0 - i32.const 16 - set_local $p2 - get_local $l5 - get_local $l6 - i32.sub - tee_local $l1 - i32.const 16 - i32.and - i32.eqz - br_if $B21 - end - get_local $l0 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $l0 - get_local $p1 - i32.load8_u offset=2 - i32.store8 offset=2 - get_local $l0 - get_local $p1 - i32.load8_u offset=3 - i32.store8 offset=3 - get_local $l0 - get_local $p1 - i32.load8_u offset=4 - i32.store8 offset=4 - get_local $l0 - get_local $p1 - i32.load8_u offset=5 - i32.store8 offset=5 - get_local $l0 - get_local $p1 - i32.load8_u offset=6 - i32.store8 offset=6 - get_local $l0 - get_local $p1 - i32.load8_u offset=7 - i32.store8 offset=7 - get_local $l0 - get_local $p1 - i32.load8_u offset=8 - i32.store8 offset=8 - get_local $l0 - get_local $p1 - i32.load8_u offset=9 - i32.store8 offset=9 - get_local $l0 - get_local $p1 - i32.load8_u offset=10 - i32.store8 offset=10 - get_local $l0 - get_local $p1 - i32.load8_u offset=11 - i32.store8 offset=11 - get_local $l0 - get_local $p1 - i32.load8_u offset=12 - i32.store8 offset=12 - get_local $l0 - get_local $p1 - i32.load8_u offset=13 - i32.store8 offset=13 - get_local $l0 - get_local $p1 - i32.load8_u offset=14 - i32.store8 offset=14 - get_local $l0 - get_local $p1 - i32.load8_u - i32.store8 - get_local $l0 - get_local $p1 - i32.load8_u offset=15 - i32.store8 offset=15 - get_local $l0 - get_local $p2 - i32.add - set_local $l0 - get_local $p1 - get_local $p2 - i32.add - set_local $p1 - i32.const 8 - set_local $p2 - get_local $l1 - i32.const 8 - i32.and - i32.eqz - br_if $B20 - br $B19 - end - i32.const 8 - set_local $p2 - get_local $l1 - i32.const 8 - i32.and - br_if $B19 - end - i32.const 4 - set_local $p2 - get_local $l1 - i32.const 4 - i32.and - br_if $B18 - br $B17 - end - get_local $l0 - get_local $p1 - i32.load8_u - i32.store8 - get_local $l0 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $l0 - get_local $p1 - i32.load8_u offset=2 - i32.store8 offset=2 - get_local $l0 - get_local $p1 - i32.load8_u offset=3 - i32.store8 offset=3 - get_local $l0 - get_local $p1 - i32.load8_u offset=4 - i32.store8 offset=4 - get_local $l0 - get_local $p1 - i32.load8_u offset=5 - i32.store8 offset=5 - get_local $l0 - get_local $p1 - i32.load8_u offset=6 - i32.store8 offset=6 - get_local $l0 - get_local $p1 - i32.load8_u offset=7 - i32.store8 offset=7 - get_local $l0 - get_local $p2 - i32.add - set_local $l0 - get_local $p1 - get_local $p2 - i32.add - set_local $p1 - i32.const 4 - set_local $p2 - get_local $l1 - i32.const 4 - i32.and - i32.eqz - br_if $B17 - end - get_local $l0 - get_local $p1 - i32.load8_u - i32.store8 - get_local $l0 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $l0 - get_local $p1 - i32.load8_u offset=2 - i32.store8 offset=2 - get_local $l0 - get_local $p1 - i32.load8_u offset=3 - i32.store8 offset=3 - get_local $l0 - get_local $p2 - i32.add - set_local $l0 - get_local $p1 - get_local $p2 - i32.add - set_local $p1 - i32.const 2 - set_local $p2 - get_local $l1 - i32.const 2 - i32.and - i32.eqz - br_if $B16 - br $B15 - end - i32.const 2 - set_local $p2 - get_local $l1 - i32.const 2 - i32.and - br_if $B15 - end - get_local $l1 - i32.const 1 - i32.and - br_if $B14 - br $B0 - end - get_local $l0 - get_local $p1 - i32.load8_u - i32.store8 - get_local $l0 - get_local $p1 - i32.load8_u offset=1 - i32.store8 offset=1 - get_local $l0 - get_local $p2 - i32.add - set_local $l0 - get_local $p1 - get_local $p2 - i32.add - set_local $p1 - get_local $l1 - i32.const 1 - i32.and - i32.eqz - br_if $B0 - end - get_local $l0 - get_local $p1 - i32.load8_u - i32.store8 - end - get_local $p0) - (func $f16 (type $t5) (param $p0 i32) (result i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) - block $B0 - block $B1 - block $B2 - get_local $p0 - tee_local $l0 - i32.const 3 - i32.and - i32.eqz - br_if $B2 - get_local $p0 - i32.load8_u - i32.eqz - br_if $B1 - get_local $p0 - i32.const 1 - i32.add - set_local $l0 - loop $L3 - get_local $l0 - i32.const 3 - i32.and - i32.eqz - br_if $B2 - get_local $l0 - i32.load8_u - set_local $l1 - get_local $l0 - i32.const 1 - i32.add - tee_local $l2 - set_local $l0 - get_local $l1 - br_if $L3 - end - get_local $l2 - i32.const -1 - i32.add - get_local $p0 - i32.sub - return - end - get_local $l0 - i32.const -4 - i32.add - set_local $l0 - loop $L4 - get_local $l0 - i32.const 4 - i32.add - tee_local $l0 - i32.load - tee_local $l1 - i32.const -1 - i32.xor - get_local $l1 - i32.const -16843009 - i32.add - i32.and - i32.const -2139062144 - i32.and - i32.eqz - br_if $L4 - end - get_local $l1 - i32.const 255 - i32.and - i32.eqz - br_if $B0 - loop $L5 - get_local $l0 - i32.load8_u offset=1 - set_local $l1 - get_local $l0 - i32.const 1 - i32.add - tee_local $l2 - set_local $l0 - get_local $l1 - br_if $L5 - end - get_local $l2 - get_local $p0 - i32.sub - return - end - i32.const 0 - return - end - get_local $l0 - get_local $p0 - i32.sub) - (table $T0 5 5 anyfunc) - (memory $memory (export "memory") 2) - (global $g0 (mut i32) (i32.const 67760)) - (global $__heap_base (export "__heap_base") i32 (i32.const 67760)) - (global $__data_end (export "__data_end") i32 (i32.const 2216)) - (elem (i32.const 1) $f12 $f11 $f13 $f14) - (data (i32.const 1024) "Hello World\00\10\04") - (data (i32.const 1040) "\05") - (data (i32.const 1052) "\02") - (data (i32.const 1076) "\03\00\00\00\04\00\00\00\a8\04\00\00\00\04") - (data (i32.const 1100) "\01") - (data (i32.const 1115) "\0a\ff\ff\ff\ff")) - diff --git a/examples/em_read_file.wat b/examples/em_read_file.wat new file mode 100644 index 000000000..7678e2519 --- /dev/null +++ b/examples/em_read_file.wat @@ -0,0 +1,43 @@ +(module + (type $t1 (func (param i32))) + (type $t2 (func (param i32 i32 i32) (result i32))) + (type $t3 (func (param i32) (result i32))) + (type $t4 (func (param i32 i32) (result i32))) + (func $putchar (import "env" "putchar") (type $t1)) + (func $printf (import "env" "printf") (type $t4)) + (func $sys_open (import "env" "___syscall5") (type $t2)) + (func $sys_read (import "env" "___syscall3") (type $t2)) + (func $sys_close (import "env" "___syscall6") (type $t3)) + (memory 1) + (data $filename (i32.const 0) "/Users/xxxx/Desktop/hello.txt\00") + (func $main (export "main") + ;; declare variables + (local $string_buf_addr i32) + (local $string_buf_len i32) + (local $file_access_flag i32) + (local $file_permission_flag i32) + (local $file_descriptor i32) + + ;; set variables + (set_local $string_buf_addr (i32.const 72)) ;; string_buf_addr at offset 72 + (set_local $string_buf_len (i32.const 10)) ;; string_buf_len is 5 + (set_local $file_access_flag (i32.const 02)) ;; file_access_flag has O_RDWR permission + (set_local $file_permission_flag (i32.const 700)) ;; file_permission_flag has S_IRWXU permission + + ;; open file + (call $sys_open (i32.const 0) (get_local $file_access_flag) (get_local $file_permission_flag)) ;; (path: u32, flags: c_int, mode: c_int) -> c_int + (set_local $file_descriptor) ;; set file_descriptor to the value returned by sys_open + + ;; read file content + (call $sys_read (get_local $file_descriptor) (get_local $string_buf_addr) (get_local $string_buf_len)) ;; (fd: c_int, buf: u32, count: size_t) -> ssize_t + (drop) ;; ignoring errors + + ;; close file + (call $sys_close (get_local $file_descriptor)) ;; (fd: c_int) -> c_int + (drop) ;; ignoring errors + + ;; print file content + (call $printf (get_local $string_buf_addr) (i32.const 0)) + (drop) ;; ignoring errors + ) +) diff --git a/src/apis/emscripten/README.md b/src/apis/emscripten/README.md new file mode 100644 index 000000000..218318cbe --- /dev/null +++ b/src/apis/emscripten/README.md @@ -0,0 +1,394 @@ +## HOST APIS + +#### EMSCRIPTEN APIS +###### PROCESS +- **_abort** ✅     [:top:](#host-apis) + ```rust + fn _abort() + ``` +- **abort** ✅ 🔥     [:top:](#host-apis) + ```rust + fn abort(message: u32, instance: &mut Instance) + ``` +- **abort_on_cannot_grow_memory** ✅     [:top:](#host-apis) + ```rust + fn abort_on_cannot_grow_memory() + ``` + +###### TIMING +- **_clock_gettime**     [:top:](#host-apis) + ```rust + ``` + +###### ENVIRONMENT +- **_getenv**     [:top:](#host-apis) + ```rust + ``` + +###### THREAD +- **_pthread_getspecific**     [:top:](#host-apis) + ```rust + ``` +- **_pthread_key_create**     [:top:](#host-apis) + ```rust + ``` +- **_pthread_setspecific**     [:top:](#host-apis) + ```rust + ``` +- **_unsetenv**     [:top:](#host-apis) + ```rust + ``` +- **___lock**     [:top:](#host-apis) + ```rust + ``` +- **___unlock**     [:top:](#host-apis) + ```rust + ``` + +###### MEMORY +- **_emscripten_memcpy_big** ✅ 🔥     [:top:](#host-apis) + ```rust + fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, instance: &mut Instance) -> u32 + ``` +- **enlarge_memory** ✅     [:top:](#host-apis) + ```rust + fn enlarge_memory() + ``` +- **get_total_memory** ✅     [:top:](#host-apis) + ```rust + fn get_total_memory(instance: &mut Instance) -> u32 + ``` + +###### TIMING + +- **_clock_gettime**     [:top:](#host-apis) + ```rust + ``` + +###### STATUS +- **___set_err_no**     [:top:](#host-apis) + ```rust + ``` + +------------------------------------------------------------------- + +#### EMSCRIPTEN SYSCALLS +- **access** (___syscall33)     [:top:](#host-apis) + ```rust + ``` +- **acct** (___syscall51)     [:top:](#host-apis) + ```rust + ``` +- **chdir** (___syscall12)     [:top:](#host-apis) + ```rust + ``` +- **chmod** (___syscall15)     [:top:](#host-apis) + ```rust + ``` +- **chown** (___syscall212)     [:top:](#host-apis) + ```rust + ``` +- **clock_nanosleep** (___syscall265)     [:top:](#host-apis) + ```rust + ``` +- **close** (___syscall6) ✅ ❗️     [:top:](#host-apis) + ```rust + fn close(fd: c_int) -> c_int + ``` +- **dup** (___syscall330)     [:top:](#host-apis) + ```rust + ``` +- **dup** (___syscall41)     [:top:](#host-apis) + ```rust + ``` +- **dup** (___syscall63)     [:top:](#host-apis) + ```rust + ``` +- **exit** (___syscall1) ✅     [:top:](#host-apis) + ```rust + fn exit(status: c_int) + ``` +- **faccessat** (___syscall307)     [:top:](#host-apis) + ```rust + ``` +- **fadvise** (___syscall272)     [:top:](#host-apis) + ```rust + ``` +- **fallocate** (___syscall324)     [:top:](#host-apis) + ```rust + ``` +- **fchdir** (___syscall133)     [:top:](#host-apis) + ```rust + ``` +- **fchmod** (___syscall94)     [:top:](#host-apis) + ```rust + ``` +- **fchmodat** (___syscall306)     [:top:](#host-apis) + ```rust + ``` +- **fchown** (___syscall207)     [:top:](#host-apis) + ```rust + ``` +- **fchownat** (___syscall298)     [:top:](#host-apis) + ```rust + ``` +- **fcntl** (___syscall221)     [:top:](#host-apis) + ```rust + ``` +- **fdatasync** (___syscall148)     [:top:](#host-apis) + ```rust + ``` +- **fstat** (___syscall197)     [:top:](#host-apis) + ```rust + ``` +- **fstatat** (___syscall300)     [:top:](#host-apis) + ```rust + ``` +- **fstatfs** (___syscall269)     [:top:](#host-apis) + ```rust + ``` +- **fsync** (___syscall118)     [:top:](#host-apis) + ```rust + ``` +- **ftruncate** (___syscall194)     [:top:](#host-apis) + ```rust + ``` +- **futimesat** (___syscall299)     [:top:](#host-apis) + ```rust + ``` +- **getcwd** (___syscall183)     [:top:](#host-apis) + ```rust + ``` +- **getdents** (___syscall220)     [:top:](#host-apis) + ```rust + ``` +- **getgid** (___syscall202)     [:top:](#host-apis) + ```rust + ``` +- **getgroups** (___syscall205)     [:top:](#host-apis) + ```rust + ``` +- **getpgid** (___syscall132)     [:top:](#host-apis) + ```rust + ``` +- **getpgrp** (___syscall65)     [:top:](#host-apis) + ```rust + ``` +- **getpid** (___syscall20)     [:top:](#host-apis) + ```rust + ``` +- **getppid** (___syscall64)     [:top:](#host-apis) + ```rust + ``` +- **getpriority** (___syscall96)     [:top:](#host-apis) + ```rust + ``` +- **getresgid** (___syscall211)     [:top:](#host-apis) + ```rust + ``` +- **getrusage** (___syscall77)     [:top:](#host-apis) + ```rust + ``` +- **getsid** (___syscall147)     [:top:](#host-apis) + ```rust + ``` +- **ioctl** (___syscall54)     [:top:](#host-apis) + ```rust + ``` +- **lchown** (___syscall198)     [:top:](#host-apis) + ```rust + ``` +- **link** (___syscall9)     [:top:](#host-apis) + ```rust + ``` +- **linkat** (___syscall303)     [:top:](#host-apis) + ```rust + ``` +- **llseek** (___syscall140)     [:top:](#host-apis) + ```rust + ``` +- **lstat** (___syscall196)     [:top:](#host-apis) + ```rust + ``` +- **madvise** (___syscall219)     [:top:](#host-apis) + ```rust + ``` +- **mincore** (___syscall218)     [:top:](#host-apis) + ```rust + ``` +- **mkdir** (___syscall39)     [:top:](#host-apis) + ```rust + ``` +- **mkdirat** (___syscall296)     [:top:](#host-apis) + ```rust + ``` +- **mknod** (___syscall14)     [:top:](#host-apis) + ```rust + ``` +- **mknodat** (___syscall297)     [:top:](#host-apis) + ```rust + ``` +- **mmap** (___syscall192)     [:top:](#host-apis) + ```rust + ``` +- **mprotect** (___syscall125)     [:top:](#host-apis) + ```rust + ``` +- **mremap** (___syscall163)     [:top:](#host-apis) + ```rust + ``` +- **msync** (___syscall144)     [:top:](#host-apis) + ```rust + ``` +- **munlockall** (___syscall153)     [:top:](#host-apis) + ```rust + ``` +- **munmap** (___syscall91)     [:top:](#host-apis) + ```rust + ``` +- **newselect** (___syscall142)     [:top:](#host-apis) + ```rust + ``` +- **nice** (___syscall34)     [:top:](#host-apis) + ```rust + ``` +- **open** (___syscall5) ✅ ❗️ 🔥     [:top:](#host-apis) + ```rust + fn open(path: u32, flags: c_int, mode: c_int, instance: &mut Instance) -> c_int + ``` +- **openat** (___syscall295)     [:top:](#host-apis) + ```rust + ``` +- **pause** (___syscall29)     [:top:](#host-apis) + ```rust + ``` +- **pipe** (___syscall331)     [:top:](#host-apis) + ```rust + ``` +- **pipe** (___syscall42)     [:top:](#host-apis) + ```rust + ``` +- **poll** (___syscall168)     [:top:](#host-apis) + ```rust + ``` +- **pread** (___syscall180)     [:top:](#host-apis) + ```rust + ``` +- **preadv** (___syscall333)     [:top:](#host-apis) + ```rust + ``` +- **prlimit** (___syscall340)     [:top:](#host-apis) + ```rust + ``` +- **pselect** (___syscall308)     [:top:](#host-apis) + ```rust + ``` +- **pwrite** (___syscall181)     [:top:](#host-apis) + ```rust + ``` +- **pwritev** (___syscall334)     [:top:](#host-apis) + ```rust + ``` +- **read** (___syscall3) ✅ ❗️     [:top:](#host-apis) + ```rust + fn read(fd: c_int, buf: u32, count: size_t, instance: &mut Instance) -> ssize_t + ``` +- **readlink** (___syscall85)     [:top:](#host-apis) + ```rust + ``` +- **readlinkat** (___syscall305)     [:top:](#host-apis) + ```rust + ``` +- **readv** (___syscall145)     [:top:](#host-apis) + ```rust + ``` +- **recvmmsg** (___syscall337)     [:top:](#host-apis) + ```rust + ``` +- **rename** (___syscall38)     [:top:](#host-apis) + ```rust + ``` +- **renameat** (___syscall302)     [:top:](#host-apis) + ```rust + ``` +- **rmdir** (___syscall40)     [:top:](#host-apis) + ```rust + ``` +- **rt_sigqueueinfo** (___syscall178)     [:top:](#host-apis) + ```rust + ``` +- **sendmmsg** (___syscall345)     [:top:](#host-apis) + ```rust + ``` +- **setdomainname** (___syscall121)     [:top:](#host-apis) + ```rust + ``` +- **setgid** (___syscall214)     [:top:](#host-apis) + ```rust + ``` +- **setitimer** (___syscall104)     [:top:](#host-apis) + ```rust + ``` +- **setpgid** (___syscall57)     [:top:](#host-apis) + ```rust + ``` +- **setpriority** (___syscall97)     [:top:](#host-apis) + ```rust + ``` +- **setresgid** (___syscall210)     [:top:](#host-apis) + ```rust + ``` +- **setrlimit** (___syscall75)     [:top:](#host-apis) + ```rust + ``` +- **setsid** (___syscall66)     [:top:](#host-apis) + ```rust + ``` +- **socketcall** (___syscall102)     [:top:](#host-apis) + ```rust + ``` +- **stat** (___syscall195)     [:top:](#host-apis) + ```rust + ``` +- **statfs** (___syscall268)     [:top:](#host-apis) + ```rust + ``` +- **symlink** (___syscall83)     [:top:](#host-apis) + ```rust + ``` +- **symlinkat** (___syscall304)     [:top:](#host-apis) + ```rust + ``` +- **sync** (___syscall36)     [:top:](#host-apis) + ```rust + ``` +- **truncate** (___syscall193)     [:top:](#host-apis) + ```rust + ``` +- **ugetrlimit** (___syscall191)     [:top:](#host-apis) + ```rust + ``` +- **umask** (___syscall60)     [:top:](#host-apis) + ```rust + ``` +- **uname** (___syscall122)     [:top:](#host-apis) + ```rust + ``` +- **unlink** (___syscall10)     [:top:](#host-apis) + ```rust + ``` +- **unlinkat** (___syscall301)     [:top:](#host-apis) + ```rust + ``` +- **utimensat** (___syscall320)     [:top:](#host-apis) + ```rust + ``` +- **wait** (___syscall114)     [:top:](#host-apis) + ```rust + ``` +- **write** (___syscall4)     [:top:](#host-apis) + ```rust + ``` +- **writev** (___syscall146)     [:top:](#host-apis) + ```rust + ``` diff --git a/src/linkers/emscripten/printf.rs b/src/apis/emscripten/io.rs similarity index 88% rename from src/linkers/emscripten/printf.rs rename to src/apis/emscripten/io.rs index e8f4d902c..8e3eb7ba5 100644 --- a/src/linkers/emscripten/printf.rs +++ b/src/apis/emscripten/io.rs @@ -2,6 +2,10 @@ use libc::printf as _printf; use crate::webassembly::Instance; +/// putchar +pub use libc::putchar; + +/// printf pub extern "C" fn printf(memory_offset: i32, extra: i32, instance: &Instance) -> i32 { let mem = &instance.memories[0]; return unsafe { diff --git a/src/apis/emscripten/memory.rs b/src/apis/emscripten/memory.rs new file mode 100644 index 000000000..fb59496b8 --- /dev/null +++ b/src/apis/emscripten/memory.rs @@ -0,0 +1,25 @@ +use libc::{ + c_void, + size_t, + memcpy, +}; + +use crate::webassembly::{Instance}; + +/// emscripten: _emscripten_memcpy_big +pub extern "C" fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, instance: &mut Instance) -> u32 { + let dest_addr = instance.memory_offset_addr(0, dest as usize) as *mut c_void; + let src_addr = instance.memory_offset_addr(0, src as usize) as *mut c_void; + unsafe { memcpy(dest_addr, src_addr, len as size_t); } + dest +} + +/// emscripten: getTotalMemory +pub extern "C" fn get_total_memory(instance: &mut Instance) -> u32 { + instance.memories[0].current_size() +} + +/// emscripten: enlargeMemory +pub extern "C" fn enlarge_memory() { + // stub +} diff --git a/src/linkers/emscripten/mod.rs b/src/apis/emscripten/mod.rs similarity index 53% rename from src/linkers/emscripten/mod.rs rename to src/apis/emscripten/mod.rs index b269a6300..41f53ca94 100644 --- a/src/linkers/emscripten/mod.rs +++ b/src/apis/emscripten/mod.rs @@ -1,20 +1,29 @@ use crate::webassembly::{ImportObject, ImportValue}; -mod abort; -mod printf; -mod putchar; -mod syscalls; +// EMSCRIPTEN APIS +mod memory; +mod process; +mod io; + +// SYSCALLS +use super::host; pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { let mut import_object = ImportObject::new(); - import_object.set("env", "printf", ImportValue::Func(printf::printf as *const u8)); - import_object.set("env", "putchar", ImportValue::Func(putchar::putchar as *const u8)); - import_object.set("env", "abort", ImportValue::Func(abort::abort as *const u8)); - import_object.set("env", "_abort", ImportValue::Func(abort::abort as *const u8)); - // SYSCALLS - import_object.set("env", "__syscall1", ImportValue::Func(syscalls::__syscall1 as *const u8)); - import_object.set("env", "__syscall3", ImportValue::Func(syscalls::__syscall3 as *const u8)); - import_object.set("env", "__syscall5", ImportValue::Func(syscalls::__syscall5 as *const u8)); + import_object.set("env", "printf", ImportValue::Func(io::printf as *const u8)); + import_object.set("env", "putchar", ImportValue::Func(io::putchar as *const u8)); + // EMSCRIPTEN SYSCALLS + import_object.set("env", "___syscall1", ImportValue::Func(host::sys_exit as *const u8)); + import_object.set("env", "___syscall3", ImportValue::Func(host::sys_read as *const u8)); + import_object.set("env", "___syscall5", ImportValue::Func(host::sys_open as *const u8)); + import_object.set("env", "___syscall6", ImportValue::Func(host::sys_close as *const u8)); + // EMSCRIPTEN APIS + import_object.set("env", "abort", ImportValue::Func(process::em_abort as *const u8)); + import_object.set("env", "_abort", ImportValue::Func(process::_abort as *const u8)); + import_object.set("env", "abortOnCannotGrowMemory", ImportValue::Func(process::abort_on_cannot_grow_memory as *const u8)); + import_object.set("env", "_emscripten_memcpy_big", ImportValue::Func(memory::_emscripten_memcpy_big as *const u8)); + import_object.set("env", "enlargeMemory", ImportValue::Func(memory::enlarge_memory as *const u8)); + import_object.set("env", "getTotalMemory", ImportValue::Func(memory::get_total_memory as *const u8)); import_object } diff --git a/src/apis/emscripten/process.rs b/src/apis/emscripten/process.rs new file mode 100644 index 000000000..0ff0badd1 --- /dev/null +++ b/src/apis/emscripten/process.rs @@ -0,0 +1,39 @@ +use libc::{ + // c_int, + // c_void, + c_char, + // size_t, + // ssize_t, + abort, +}; + +use std::ffi::CStr; +use crate::webassembly::{Instance}; + +extern "C" fn abort_with_message(message: &str) { + println!("{}", message); + _abort(); +} + +/// emscripten: _abort +pub extern "C" fn _abort() { + unsafe { abort(); } +} + +/// emscripten: abort +pub extern "C" fn em_abort(message: u32, instance: &mut Instance) { + let message_addr = instance.memory_offset_addr(0, message as usize) as *mut c_char; + unsafe { + let message = CStr::from_ptr(message_addr) + .to_str() + .unwrap_or("Unexpected abort"); + + abort_with_message(message); + } +} + +/// emscripten: abortOnCannotGrowMemory +pub extern "C" fn abort_on_cannot_grow_memory() { + abort_with_message("Cannot enlarge memory arrays!"); +} + diff --git a/src/linkers/emscripten/tests/printf.wast b/src/apis/emscripten/tests/printf.wast similarity index 100% rename from src/linkers/emscripten/tests/printf.wast rename to src/apis/emscripten/tests/printf.wast diff --git a/src/linkers/emscripten/tests/putchar.wast b/src/apis/emscripten/tests/putchar.wast similarity index 100% rename from src/linkers/emscripten/tests/putchar.wast rename to src/apis/emscripten/tests/putchar.wast diff --git a/src/apis/gcc/.gitignore b/src/apis/gcc/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/src/apis/host/mod.rs b/src/apis/host/mod.rs new file mode 100644 index 000000000..d92dd7201 --- /dev/null +++ b/src/apis/host/mod.rs @@ -0,0 +1,4 @@ +mod posix; + +// TODO: Make portable +pub use self::posix::*; diff --git a/src/apis/host/posix/mod.rs b/src/apis/host/posix/mod.rs new file mode 100644 index 000000000..18ed9d0bf --- /dev/null +++ b/src/apis/host/posix/mod.rs @@ -0,0 +1,3 @@ +pub mod syscalls; + +pub use self::syscalls::*; diff --git a/src/apis/host/posix/syscalls.rs b/src/apis/host/posix/syscalls.rs new file mode 100644 index 000000000..42124201e --- /dev/null +++ b/src/apis/host/posix/syscalls.rs @@ -0,0 +1,37 @@ +/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset + +use libc::{ + c_int, + c_void, + size_t, + ssize_t, + exit, + read, + open, + close, +}; + +use crate::webassembly::{Instance}; + +/// emscripten: ___syscall1 +pub extern "C" fn sys_exit(status: c_int) { + unsafe { exit(status); } +} + +/// emscripten: ___syscall3 +pub extern "C" fn sys_read(fd: c_int, buf: u32, count: size_t, instance: &mut Instance) -> ssize_t { + let buf_addr = instance.memory_offset_addr(0, buf as usize) as *mut c_void; + unsafe { read(fd, buf_addr, count) } +} + +/// emscripten: ___syscall5 +pub extern "C" fn sys_open(path: u32, flags: c_int, mode: c_int, instance: &mut Instance) -> c_int { + let path_addr = instance.memory_offset_addr(0, path as usize) as *const i8; + unsafe { open(path_addr, flags, mode) } +} + +/// emscripten: ___syscall6 +pub extern "C" fn sys_close(fd: c_int) -> c_int { + unsafe { close(fd) } +} + diff --git a/src/apis/llvm/.gitignore b/src/apis/llvm/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/src/linkers/mod.rs b/src/apis/mod.rs similarity index 82% rename from src/linkers/mod.rs rename to src/apis/mod.rs index ef78d9e06..0c83d3b3f 100644 --- a/src/linkers/mod.rs +++ b/src/apis/mod.rs @@ -1,3 +1,5 @@ pub mod emscripten; +pub mod host; pub use self::emscripten::generate_emscripten_env; + diff --git a/src/linkers/emscripten/README.md b/src/linkers/emscripten/README.md deleted file mode 100644 index b19c4de6c..000000000 --- a/src/linkers/emscripten/README.md +++ /dev/null @@ -1,389 +0,0 @@ -# HOST APIS - -## EMSCRIPTEN APIS -#### PROCESS -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` - -#### THREAD -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- abort     [:top:](#host-apis) -```rust -fn abort() -``` -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` - -#### MEMORY -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` - -#### TIMING - -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` - -#### STATUS -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` - -## EMSCRIPTEN SYSCALLS -- SYS_fstat (___syscall197)     [:top:](#host-apis) -```rust -``` -- SYS_getdents (___syscall220)     [:top:](#host-apis) -```rust -``` -- SYS_lstat (___syscall196)     [:top:](#host-apis) -```rust -``` -- SYS_stat (___syscall195)     [:top:](#host-apis) -```rust -``` -- access (___syscall33)     [:top:](#host-apis) -```rust -``` -- acct (___syscall51)     [:top:](#host-apis) -```rust -``` -- chdir (___syscall12)     [:top:](#host-apis) -```rust -``` -- chmod (___syscall15)     [:top:](#host-apis) -```rust -``` -- chown (___syscall212)     [:top:](#host-apis) -```rust -``` -- clock_nanosleep (___syscall265)     [:top:](#host-apis) -```rust -``` -- close (___syscall6)     [:top:](#host-apis) -```rust -``` -- dup (___syscall330)     [:top:](#host-apis) -```rust -``` -- dup (___syscall41)     [:top:](#host-apis) -```rust -``` -- dup (___syscall63)     [:top:](#host-apis) -```rust -``` -- exit (___syscall1)     [:top:](#host-apis) -```rust -fn exit(status: c_int) -``` -- faccessat (___syscall307)     [:top:](#host-apis) -```rust -``` -- fadvise (___syscall272)     [:top:](#host-apis) -```rust -``` -- fallocate (___syscall324)     [:top:](#host-apis) -```rust -``` -- fchdir (___syscall133)     [:top:](#host-apis) -```rust -``` -- fchmod (___syscall94)     [:top:](#host-apis) -```rust -``` -- fchmodat (___syscall306)     [:top:](#host-apis) -```rust -``` -- fchown (___syscall207)     [:top:](#host-apis) -```rust -``` -- fchownat (___syscall298)     [:top:](#host-apis) -```rust -``` -- fcntl (___syscall221)     [:top:](#host-apis) -```rust -``` -- fdatasync (___syscall148)     [:top:](#host-apis) -```rust -``` -- fstatat (___syscall300)     [:top:](#host-apis) -```rust -``` -- fstatfs (___syscall269)     [:top:](#host-apis) -```rust -``` -- fsync (___syscall118)     [:top:](#host-apis) -```rust -``` -- ftruncate (___syscall194)     [:top:](#host-apis) -```rust -``` -- futimesat (___syscall299)     [:top:](#host-apis) -```rust -``` -- getcwd (___syscall183)     [:top:](#host-apis) -```rust -``` -- getgid (___syscall202)     [:top:](#host-apis) -```rust -``` -- getgroups (___syscall205)     [:top:](#host-apis) -```rust -``` -- getpgid (___syscall132)     [:top:](#host-apis) -```rust -``` -- getpgrp (___syscall65)     [:top:](#host-apis) -```rust -``` -- getpid (___syscall20)     [:top:](#host-apis) -```rust -``` -- getppid (___syscall64)     [:top:](#host-apis) -```rust -``` -- getpriority (___syscall96)     [:top:](#host-apis) -```rust -``` -- getresgid (___syscall211)     [:top:](#host-apis) -```rust -``` -- getrusage (___syscall77)     [:top:](#host-apis) -```rust -``` -- getsid (___syscall147)     [:top:](#host-apis) -```rust -``` -- ioctl (___syscall54)     [:top:](#host-apis) -```rust -``` -- lchown (___syscall198)     [:top:](#host-apis) -```rust -``` -- link (___syscall9)     [:top:](#host-apis) -```rust -``` -- linkat (___syscall303)     [:top:](#host-apis) -```rust -``` -- llseek (___syscall140)     [:top:](#host-apis) -```rust -``` -- madvise (___syscall219)     [:top:](#host-apis) -```rust -``` -- mincore (___syscall218)     [:top:](#host-apis) -```rust -``` -- mkdir (___syscall39)     [:top:](#host-apis) -```rust -``` -- mkdirat (___syscall296)     [:top:](#host-apis) -```rust -``` -- mknod (___syscall14)     [:top:](#host-apis) -```rust -``` -- mknodat (___syscall297)     [:top:](#host-apis) -```rust -``` -- mmap (___syscall192)     [:top:](#host-apis) -```rust -``` -- mprotect (___syscall125)     [:top:](#host-apis) -```rust -``` -- mremap (___syscall163)     [:top:](#host-apis) -```rust -``` -- msync (___syscall144)     [:top:](#host-apis) -```rust -``` -- munlockall (___syscall153)     [:top:](#host-apis) -```rust -``` -- munmap (___syscall91)     [:top:](#host-apis) -```rust -``` -- newselect (___syscall142)     [:top:](#host-apis) -```rust -``` -- nice (___syscall34)     [:top:](#host-apis) -```rust -``` -- open (___syscall5)     [:top:](#host-apis) -```rust -fn open(path: *const c_char, oflag: c_int, ...) -> c_int -``` -- openat (___syscall295)     [:top:](#host-apis) -```rust -``` -- pause (___syscall29)     [:top:](#host-apis) -```rust -``` -- pipe (___syscall331)     [:top:](#host-apis) -```rust -``` -- pipe (___syscall42)     [:top:](#host-apis) -```rust -``` -- poll (___syscall168)     [:top:](#host-apis) -```rust -``` -- pread (___syscall180)     [:top:](#host-apis) -```rust -``` -- preadv (___syscall333)     [:top:](#host-apis) -```rust -``` -- prlimit (___syscall340)     [:top:](#host-apis) -```rust -``` -- pselect (___syscall308)     [:top:](#host-apis) -```rust -``` -- pwrite (___syscall181)     [:top:](#host-apis) -```rust -``` -- pwritev (___syscall334)     [:top:](#host-apis) -```rust -``` -- read (___syscall3)     [:top:](#host-apis) -```rust -fn read(fd: usize, buf: *mut c_void, count: usize) -> isize -``` -- readlink (___syscall85)     [:top:](#host-apis) -```rust -``` -- readlinkat (___syscall305)     [:top:](#host-apis) -```rust -``` -- readv (___syscall145)     [:top:](#host-apis) -```rust -``` -- recvmmsg (___syscall337)     [:top:](#host-apis) -```rust -``` -- rename (___syscall38)     [:top:](#host-apis) -```rust -``` -- renameat (___syscall302)     [:top:](#host-apis) -```rust -``` -- rmdir (___syscall40)     [:top:](#host-apis) -```rust -``` -- rt_sigqueueinfo (___syscall178)     [:top:](#host-apis) -```rust -``` -- sendmmsg (___syscall345)     [:top:](#host-apis) -```rust -``` -- setdomainname (___syscall121)     [:top:](#host-apis) -```rust -``` -- setgid (___syscall214)     [:top:](#host-apis) -```rust -``` -- setitimer (___syscall104)     [:top:](#host-apis) -```rust -``` -- setpgid (___syscall57)     [:top:](#host-apis) -```rust -``` -- setpriority (___syscall97)     [:top:](#host-apis) -```rust -``` -- setresgid (___syscall210)     [:top:](#host-apis) -```rust -``` -- setrlimit (___syscall75)     [:top:](#host-apis) -```rust -``` -- setsid (___syscall66)     [:top:](#host-apis) -```rust -``` -- socketcall (___syscall102)     [:top:](#host-apis) -```rust -``` -- statfs (___syscall268)     [:top:](#host-apis) -```rust -``` -- symlink (___syscall83)     [:top:](#host-apis) -```rust -``` -- symlinkat (___syscall304)     [:top:](#host-apis) -```rust -``` -- sync (___syscall36)     [:top:](#host-apis) -```rust -``` -- truncate (___syscall193)     [:top:](#host-apis) -```rust -``` -- ugetrlimit (___syscall191)     [:top:](#host-apis) -```rust -``` -- umask (___syscall60)     [:top:](#host-apis) -```rust -``` -- uname (___syscall122)     [:top:](#host-apis) -```rust -``` -- unlink (___syscall10)     [:top:](#host-apis) -```rust -``` -- unlinkat (___syscall301)     [:top:](#host-apis) -```rust -``` -- utimensat (___syscall320)     [:top:](#host-apis) -```rust -``` -- wait (___syscall114)     [:top:](#host-apis) -```rust -``` -- write (___syscall4)     [:top:](#host-apis) -```rust -``` -- writev (___syscall146)     [:top:](#host-apis) -```rust -``` diff --git a/src/linkers/emscripten/abort.rs b/src/linkers/emscripten/abort.rs deleted file mode 100644 index e2662bd19..000000000 --- a/src/linkers/emscripten/abort.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::webassembly::Instance; -use std::process; - -pub extern "C" fn abort(_code: i32, _instance: &Instance) { - process::abort(); - // abort!("Aborted") -} diff --git a/src/linkers/emscripten/putchar.rs b/src/linkers/emscripten/putchar.rs deleted file mode 100644 index 20309b020..000000000 --- a/src/linkers/emscripten/putchar.rs +++ /dev/null @@ -1 +0,0 @@ -pub use libc::putchar; diff --git a/src/linkers/emscripten/syscalls/darwin/mod.rs b/src/linkers/emscripten/syscalls/darwin/mod.rs deleted file mode 100644 index 1d7397e2f..000000000 --- a/src/linkers/emscripten/syscalls/darwin/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod syscalls; diff --git a/src/linkers/emscripten/syscalls/darwin/syscalls.rs b/src/linkers/emscripten/syscalls/darwin/syscalls.rs deleted file mode 100644 index dc7a64ff4..000000000 --- a/src/linkers/emscripten/syscalls/darwin/syscalls.rs +++ /dev/null @@ -1,25 +0,0 @@ -use libc::{ - c_int, - c_void, - c_char, - size_t, - ssize_t, - open, - exit, - read, -}; - -/// exit -pub extern "C" fn __syscall1(status: c_int) { - unsafe { exit(status); } -} - -/// read -pub extern "C" fn __syscall3(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t { - unsafe { read(fd, buf, count) } -} - -/// open -pub extern "C" fn __syscall5(path: *const c_char, oflag: c_int) -> c_int { - unsafe { open(path, oflag) } -} diff --git a/src/linkers/emscripten/syscalls/mod.rs b/src/linkers/emscripten/syscalls/mod.rs deleted file mode 100644 index 8b5a6894d..000000000 --- a/src/linkers/emscripten/syscalls/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod darwin; - -pub use self::darwin::syscalls::*; diff --git a/src/main.rs b/src/main.rs index bb181aecf..743556f34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ use structopt::StructOpt; #[macro_use] mod macros; pub mod common; -pub mod linkers; +pub mod apis; pub mod sighandler; #[cfg(test)] mod spectests; @@ -71,12 +71,12 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> { .map_err(|err| format!("Can't convert from wast to wasm: {:?}", err))?; } - let import_object = linkers::generate_emscripten_env(); + let import_object = apis::generate_emscripten_env(); let webassembly::ResultObject { module, instance } = webassembly::instantiate(wasm_binary, import_object) .map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?; - webassembly::utils::print_instance_offsets(&instance); + // webassembly::utils::print_instance_offsets(&instance); let func_index = instance .start_func diff --git a/src/spectests/_common.rs b/src/spectests/_common.rs index 0920378b5..3511b5d9a 100644 --- a/src/spectests/_common.rs +++ b/src/spectests/_common.rs @@ -12,7 +12,7 @@ pub fn spectest_importobject<'a, 'b>() -> ImportObject<&'a str, &'b str> { let mut import_object = ImportObject::new(); import_object.set("spectest", "print_i32", ImportValue::Func(print_i32 as *const u8)); import_object.set("spectest", "print", ImportValue::Func(print as *const u8)); - import_object.set("spectest", "global_i32", ImportValue::Func(GLOBAL_I32 as *const u8)); + import_object.set("spectest", "global_i32", ImportValue::Global(GLOBAL_I32 as _)); import_object.set("spectest", "table", ImportValue::Table(vec![0; 30])); return import_object; } diff --git a/src/webassembly/import_object.rs b/src/webassembly/import_object.rs index 7e7411d29..7d78dab59 100644 --- a/src/webassembly/import_object.rs +++ b/src/webassembly/import_object.rs @@ -112,7 +112,7 @@ where #[derive(PartialEq, Debug)] pub enum ImportValue { Func(*const u8), - Global(u8), + Global(i64), Table(Vec), Memory(LinearMemory), } diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index 3901988aa..99393b7a1 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -9,7 +9,7 @@ use cranelift_codegen::ir::LibCall; use cranelift_codegen::{binemit, Context}; use cranelift_entity::EntityRef; -use cranelift_wasm::{FuncIndex, GlobalInit}; +use cranelift_wasm::{FuncIndex, GlobalInit, GlobalIndex}; use cranelift_codegen::isa::TargetIsa; use region; use std::iter::Iterator; @@ -22,8 +22,7 @@ use super::super::common::slice::{BoundedSlice, UncheckedSlice}; use super::errors::ErrorKind; use super::import_object::{ImportObject, ImportValue}; use super::memory::LinearMemory; -use super::module::Export; -use super::module::Module; +use super::module::{Export, ImportableExportable, Module}; use super::relocation::{Reloc, RelocSink, RelocationType}; use super::math_intrinsics; @@ -121,9 +120,9 @@ pub struct InstanceOptions { pub isa: Box, } -// extern fn mock_fn() -> i32 { -// return 0; -// } +extern fn mock_fn() -> i32 { + return 0; +} impl Instance { pub const TABLES_OFFSET: usize = 0; // 0 on 64-bit | 0 on 32-bit @@ -145,9 +144,6 @@ impl Instance { let mut functions: Vec> = Vec::new(); let mut import_functions: Vec<*const u8> = Vec::new(); - let mut imported_memories: Vec = Vec::new(); - let mut imported_tables: Vec> = Vec::new(); - debug!("Instance - Instantiating functions"); // Instantiate functions { @@ -165,19 +161,19 @@ impl Instance { for (module, field) in module.info.imported_funcs.iter() { let imported = import_object .get(&module.as_str(), &field.as_str()); - let function = match imported { + let function: &*const u8 = match imported { Some(ImportValue::Func(f)) => f, None => { - // if options.mock_missing_imports { - // debug!("The import {}.{} is not provided, therefore will be mocked.", module, field); - // mock_fn as *const u8 - // } - // else { - return Err(ErrorKind::LinkError(format!( - "Imported function {}.{} was not provided in the import_functions", - module, field - ))); - // } + if options.mock_missing_imports { + debug!("The import {}.{} is not provided, therefore will be mocked.", module, field); + &(mock_fn as *const u8) + } + else { + return Err(ErrorKind::LinkError(format!( + "Imported function {}.{} was not provided in the import_functions", + module, field + ))); + } }, other => panic!("Expected function import, received {:?}", other) }; @@ -295,45 +291,81 @@ impl Instance { } } - // Looping through and getting the imported objects - for (_key, value) in import_object.map { - match value { - ImportValue::Memory(value) => - imported_memories.push(value), - ImportValue::Table(value) => - imported_tables.push(value), - _ => (), + debug!("Instance - Instantiating globals"); + // Instantiate Globals + let globals_data = { + let globals_count = module.info.globals.len(); + // Allocate the underlying memory and initialize it to zeros + let globals_data_size = globals_count * 8; + globals.resize(globals_data_size, 0); + + // cast the globals slice to a slice of i64. + let globals_data = unsafe { + slice::from_raw_parts_mut(globals.as_mut_ptr() as *mut i64, globals_count) + }; + + for (i, global) in module.info.globals.iter().enumerate() { + let ImportableExportable {entity, import_name, ..} = global; + let value: i64 = match entity.initializer { + GlobalInit::I32Const(n) => n as _, + GlobalInit::I64Const(n) => n, + GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) }, + GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) }, + GlobalInit::GlobalRef(_global_index) => { + unimplemented!("GlobalInit::GlobalRef is not yet supported") + } + GlobalInit::Import() => { + let (module_name, field_name) = import_name.as_ref().expect("Expected a import name for the global import"); + let imported = import_object.get(&module_name.as_str(), &field_name.as_str()); + match imported { + Some(ImportValue::Global(value)) => { + *value + }, + _ => panic!("Imported global value was not provided {:?} ({}.{})", imported, module_name, field_name) + } + } + }; + globals_data[i] = value; } - } + globals_data + }; debug!("Instance - Instantiating tables"); // Instantiate tables { // Reserve space for tables - tables.reserve_exact(imported_tables.len() + module.info.tables.len()); - - // Get imported tables - for table in imported_tables { - tables.push(table); - } + tables.reserve_exact(module.info.tables.len()); // Get tables in module for table in &module.info.tables { - let len = table.entity.size; - let mut v = Vec::with_capacity(len); - v.resize(len, 0); - tables.push(v); + let table: Vec = match table.import_name.as_ref() { + Some((module_name, field_name)) => { + let imported = import_object.get(&module_name.as_str(), &field_name.as_str()); + match imported { + Some(ImportValue::Table(t)) => { + t.to_vec() + }, + _ => panic!("Imported table was not provided {:?} ({}.{})", imported, module_name, field_name) + } + }, + None => { + let len = table.entity.size; + let mut v = Vec::with_capacity(len); + v.resize(len, 0); + v + } + }; + tables.push(table); } // instantiate tables for table_element in &module.info.table_elements { - // TODO: We shouldn't assert here since we are returning a Result - assert!( - table_element.base.is_none(), - "globalvalue base not supported yet." - ); - - let base = 0; + let base = match table_element.base { + Some(global_index) => { + globals_data[global_index.index()] as usize + }, + None => 0 + }; let table = &mut tables[table_element.table_index.index()]; for (i, func_index) in table_element.elements.iter().enumerate() { @@ -343,6 +375,7 @@ impl Instance { // let func_index = *elem_index - module.info.imported_funcs.len() as u32; // let func_addr = functions[func_index.index()].as_ptr(); + println!("TABLE LENGTH: {}", table.len()); let func_addr = get_function_addr(&func_index, &import_functions, &functions); table[base + table_element.offset + i] = func_addr as _; } @@ -353,12 +386,7 @@ impl Instance { // Instantiate memories { // Reserve space for memories - memories.reserve_exact(imported_memories.len() + module.info.memories.len()); - - // Get imported memories - for memory in imported_memories { - memories.push(memory); - } + memories.reserve_exact(module.info.memories.len()); // Get memories in module for memory in &module.info.memories { @@ -379,41 +407,6 @@ impl Instance { } } - debug!("Instance - Instantiating globals"); - // TODO: Fix globals import - // Instantiate Globals - { - let globals_count = module.info.globals.len(); - // Allocate the underlying memory and initialize it to zeros - let globals_data_size = globals_count * 8; - globals.resize(globals_data_size, 0); - - // cast the globals slice to a slice of i64. - let globals_data = unsafe { - slice::from_raw_parts_mut(globals.as_mut_ptr() as *mut i64, globals_count) - }; - - for (i, global) in module.info.globals.iter().enumerate() { - let value: i64 = match global.entity.initializer { - GlobalInit::I32Const(n) => n as _, - GlobalInit::I64Const(n) => n, - GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) }, - GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) }, - GlobalInit::GlobalRef(_global_index) => { - unimplemented!("GlobalInit::GlobalRef is not yet supported") - } - GlobalInit::Import() => { - // Right now (because there is no module/field fields on the Import - // https://github.com/CraneStation/cranelift/blob/5cabce9b58ff960534d4017fad11f2e78c72ceab/lib/wasm/src/sections_translator.rs#L90-L99 ) - // It's impossible to know where to take the global from. - // This should be fixed in Cranelift itself. - unimplemented!("GlobalInit::Import is not yet supported") - } - }; - globals_data[i] = value; - } - } - let start_func: Option = module .info @@ -484,6 +477,13 @@ impl Instance { .as_ref()[address..address + len] } + pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize { + let mem = &self.memories[index]; + unsafe { + mem.mmap.as_ptr().offset(offset as isize) as *const usize + } + } + // Shows the value of a global variable. // pub fn inspect_global(&self, global_index: GlobalIndex, ty: ir::Type) -> &[u8] { // let offset = global_index * 8; @@ -496,6 +496,7 @@ impl Instance { // } } +// TODO: Needs to be moved to more appropriate place extern "C" fn grow_memory(size: u32, memory_index: u32, instance: &mut Instance) -> i32 { // TODO: Support for only one LinearMemory for now. debug_assert_eq!( diff --git a/src/webassembly/memory.rs b/src/webassembly/memory.rs index 32600fb3e..7c6910b4a 100644 --- a/src/webassembly/memory.rs +++ b/src/webassembly/memory.rs @@ -65,6 +65,11 @@ impl LinearMemory { self.current } + /// Returns the maximum number of wasm pages allowed. + pub fn maximum_size(&self) -> u32 { + self.maximum.unwrap_or(65536) + } + /// Grow memory by the specified amount of pages. /// /// Returns `None` if memory can't be grown by the specified amount diff --git a/src/webassembly/module.rs b/src/webassembly/module.rs index 1b8a76c66..bd31b060b 100644 --- a/src/webassembly/module.rs +++ b/src/webassembly/module.rs @@ -71,21 +71,25 @@ fn get_func_name(func_index: FuncIndex) -> ir::ExternalName { ir::ExternalName::user(0, func_index.index() as u32) } -/// A collection of names under which a given entity is exported. +/// A collection of names under which a given entity is imported/exported. #[derive(Debug)] -pub struct Exportable { +pub struct ImportableExportable { /// An entity. pub entity: T, /// Names under which the entity is exported. pub export_names: Vec, + + /// Names under which the entity is imported. + pub import_name: Option<(String, String)>, } -impl Exportable { - pub fn new(entity: T) -> Self { +impl ImportableExportable { + pub fn new(entity: T, import_name: Option<(String, String)>) -> Self { Self { entity, export_names: Vec::new(), + import_name: import_name } } } @@ -120,7 +124,7 @@ pub struct ModuleInfo { pub signatures: Vec, /// Functions, imported and local. - pub functions: PrimaryMap>, + pub functions: PrimaryMap>, /// Function bodies. pub function_bodies: PrimaryMap, @@ -129,7 +133,7 @@ pub struct ModuleInfo { pub imported_funcs: Vec<(String, String)>, /// Tables as provided by `declare_table`. - pub tables: Vec>, + pub tables: Vec>, /// WebAssembly table initializers. pub table_elements: Vec, @@ -138,13 +142,13 @@ pub struct ModuleInfo { pub tables_base: Option, /// Memories as provided by `declare_memory`. - pub memories: Vec>, + pub memories: Vec>, /// The Cranelift global holding the base address of the globals vector. pub globals_base: Option, /// Globals as provided by `declare_global`. - pub globals: Vec>, + pub globals: Vec>, /// The start function. pub start_func: Option, @@ -154,7 +158,7 @@ pub struct ModuleInfo { /// Exported entities /// We use this in order to have a O(1) allocation of the exports - /// rather than iterating through the Exportable elements. + /// rather than iterating through the ImportableExportable elements. pub exports: HashMap, /// The external function declaration for implementing wasm's `current_memory`. @@ -708,7 +712,7 @@ impl<'data> ModuleEnvironment<'data> for Module { self.info.imported_funcs.len(), "Imported functions must be declared first" ); - self.info.functions.push(Exportable::new(sig_index)); + self.info.functions.push(ImportableExportable::new(sig_index, None)); self.info .imported_funcs .push((String::from(module), String::from(field))); @@ -719,7 +723,7 @@ impl<'data> ModuleEnvironment<'data> for Module { } fn declare_func_type(&mut self, sig_index: SignatureIndex) { - self.info.functions.push(Exportable::new(sig_index)); + self.info.functions.push(ImportableExportable::new(sig_index, None)); } fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex { @@ -727,7 +731,16 @@ impl<'data> ModuleEnvironment<'data> for Module { } fn declare_global(&mut self, global: Global) { - self.info.globals.push(Exportable::new(global)); + self.info.globals.push(ImportableExportable::new(global, None)); + } + + fn declare_global_import( + &mut self, + global: Global, + module: &'data str, + field: &'data str, + ) { + self.info.globals.push(ImportableExportable::new(global, Some((String::from(module), String::from(field))))); } fn get_global(&self, global_index: GlobalIndex) -> &Global { @@ -735,7 +748,16 @@ impl<'data> ModuleEnvironment<'data> for Module { } fn declare_table(&mut self, table: Table) { - self.info.tables.push(Exportable::new(table)); + self.info.tables.push(ImportableExportable::new(table, None)); + } + + fn declare_table_import( + &mut self, + table: Table, + module: &'data str, + field: &'data str, + ) { + self.info.tables.push(ImportableExportable::new(table, Some((String::from(module), String::from(field))))); } fn declare_table_elements( @@ -745,7 +767,6 @@ impl<'data> ModuleEnvironment<'data> for Module { offset: usize, elements: Vec, ) { - debug_assert!(base.is_none(), "global-value offsets not supported yet"); self.info.table_elements.push(TableElements { table_index, base, @@ -755,7 +776,16 @@ impl<'data> ModuleEnvironment<'data> for Module { } fn declare_memory(&mut self, memory: Memory) { - self.info.memories.push(Exportable::new(memory)); + self.info.memories.push(ImportableExportable::new(memory, None)); + } + + fn declare_memory_import( + &mut self, + memory: Memory, + module: &'data str, + field: &'data str, + ) { + self.info.memories.push(ImportableExportable::new(memory, Some((String::from(module), String::from(field))))); } fn declare_data_initialization(