Collects README links at the bottom (#515)
Collecting README links at the bottom helps with formatting. I made some editorial changes, notably pointing people at the WebAssembly 2.0 issue which I'm fleshing out separately. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
233
README.md
233
README.md
@@ -4,15 +4,17 @@ WebAssembly is a way to safely run code compiled in other languages. Runtimes
|
||||
execute WebAssembly Modules (Wasm), which are most often binaries with a `.wasm`
|
||||
extension.
|
||||
|
||||
wazero is a [WebAssembly 1.0 (20191205)](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/) spec compliant runtime written in Go.
|
||||
It has *zero dependencies*, and doesn't rely on CGO. This means you can
|
||||
run applications in other languages and still keep cross compilation.
|
||||
wazero is a [WebAssembly 1.0][1] spec compliant runtime written in Go. It has
|
||||
*zero dependencies*, and doesn't rely on CGO. This means you can run
|
||||
applications in other languages and still keep cross compilation.
|
||||
|
||||
Import wazero and extend your Go application with code written in any language!
|
||||
|
||||
## Example
|
||||
|
||||
The best way to learn this and other features you get with wazero is by trying one of our [examples](examples).
|
||||
The best way to learn this and other features you get with wazero is by trying
|
||||
one of our [examples](examples).
|
||||
|
||||
For the impatient, here's how invoking a factorial function looks in wazero:
|
||||
|
||||
```golang
|
||||
@@ -22,7 +24,7 @@ func main() {
|
||||
|
||||
// Read a WebAssembly binary containing an exported "fac" function.
|
||||
// * Ex. (func (export "fac") (param i64) (result i64) ...
|
||||
source, _ := os.ReadFile("./tests/bench/testdata/fac.wasm")
|
||||
source, _ := os.ReadFile("./path/to/fac.wasm")
|
||||
|
||||
// Instantiate the module and return its exported functions
|
||||
module, _ := wazero.NewRuntime().InstantiateModuleFromCode(ctx, source)
|
||||
@@ -33,9 +35,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
Note: While the [source for this](internal/integration_test/bench/testdata/fac.wat) is in the
|
||||
WebAssembly 1.0 (20191205) Text Format, it could have been written in another
|
||||
language that compiles to (targets) WebAssembly, such as AssemblyScript, C, C++, Rust, TinyGo or Zig.
|
||||
Note: `fac.wasm` was compiled from [fac.wat][3], in the [WebAssembly 1.0][1]
|
||||
Text Format, it could have been written in another language that compiles to
|
||||
(targets) WebAssembly, such as AssemblyScript, C, C++, Rust, TinyGo or Zig.
|
||||
|
||||
## Deeper dive
|
||||
|
||||
@@ -66,11 +68,11 @@ if err != nil {
|
||||
defer env.Close(ctx)
|
||||
```
|
||||
|
||||
While not a standards body like W3C, there is another dominant community in the
|
||||
WebAssembly ecosystem: [The Bytecode Alliance](https://github.com/bytecodealliance/governance).
|
||||
The Bytecode Alliance controls the WebAssembly System Interface ([WASI](https://github.com/WebAssembly/WASI)),
|
||||
which is a set of function imports similar to Go's [x/sys/unix](https://pkg.go.dev/golang.org/x/sys/unix).
|
||||
The "wasi_snapshot_preview1" version of WASI is widely implemented, so wazero
|
||||
The WebAssembly community has [subgroups][4] which maintain work that may not
|
||||
result in a Web Standard. One such group is the WebAssembly System Interface
|
||||
([WASI][5]), which defines functions similar to Go's [x/sys/unix][6].
|
||||
|
||||
The [wasi_snapshot_preview1][13] tag of WASI is widely implemented, so wazero
|
||||
bundles an implementation. That way, you don't have to write these functions.
|
||||
|
||||
For example, here's how you can allow WebAssembly modules to read
|
||||
@@ -91,42 +93,59 @@ they may answer them for you!
|
||||
|
||||
## Runtime
|
||||
|
||||
There are two runtime configurations supported in wazero, where _JIT_ is default:
|
||||
|
||||
1. _Interpreter_: a naive interpreter-based implementation of Wasm virtual machine. Its implementation doesn't have any platform (GOARCH, GOOS) specific code, therefore _interpreter_ can be used for any compilation target available for Go (such as `riscv64`).
|
||||
2. _JIT_: compiles WebAssembly modules, generates the machine code, and executing it all at runtime. Currently wazero implements the JIT compiler for `amd64` and `arm64` target. Generally speaking, _JIT_ is faster than _Interpreter_ by order of magnitude. However, the implementation is immature and has a bunch of aspects that could be improved (for example, it just does a singlepass compilation and doesn't do any optimizations, etc.). Please refer to [internal/wasm/jit/RATIONALE.md](internal/wasm/jit/RATIONALE.md) for the design choices and considerations in our JIT compiler.
|
||||
|
||||
Both configurations pass 100% of [WebAssembly spec test suites]((https://github.com/WebAssembly/spec/tree/wg-1.0/test/core)) (on supported platforms).
|
||||
|
||||
| Runtime | Usage| amd64 | arm64 | others |
|
||||
|:---:|:---:|:---:|:---:|:---:|
|
||||
| Interpreter|`wazero.NewRuntimeConfigInterpreter()`|✅ |✅|✅|
|
||||
| JIT |`wazero.NewRuntimeConfigJIT()`|✅|✅ |❌|
|
||||
There are two runtime configurations supported in wazero: _JIT_ is default:
|
||||
|
||||
If you don't choose, ex `wazero.NewRuntime()`, JIT is used if supported. You can also force the interpreter like so:
|
||||
```go
|
||||
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
|
||||
```
|
||||
|
||||
### Interpreter
|
||||
Interpreter is a naive interpreter-based implementation of Wasm virtual
|
||||
machine. Its implementation doesn't have any platform (GOARCH, GOOS) specific
|
||||
code, therefore _interpreter_ can be used for any compilation target available
|
||||
for Go (such as `riscv64`).
|
||||
|
||||
### JIT
|
||||
JIT (Just In Time) compiles WebAssembly modules into machine code during
|
||||
`Runtime.CompileModule` so that they are executed natively at runtime. JIT is
|
||||
faster than Interpreter, often by order of magnitude (10x) or more. This is
|
||||
done while still having no host-specific dependencies.
|
||||
|
||||
If interested, check out the [RATIONALE.md][8] and help us optimize further!
|
||||
|
||||
### Conformance
|
||||
|
||||
Both runtimes pass [WebAssembly 1.0 spectests][7] on supported platforms:
|
||||
|
||||
| Runtime | Usage| amd64 | arm64 | others |
|
||||
|:---:|:---:|:---:|:---:|:---:|
|
||||
| Interpreter|`wazero.NewRuntimeConfigInterpreter()`|✅ |✅|✅|
|
||||
| JIT |`wazero.NewRuntimeConfigJIT()`|✅|✅ |❌|
|
||||
|
||||
## Support Policy
|
||||
|
||||
The below support policy focuses on compatability concerns of those embedding wazero into their Go applications.
|
||||
The below support policy focuses on compatability concerns of those embedding
|
||||
wazero into their Go applications.
|
||||
|
||||
### wazero
|
||||
|
||||
wazero is an early project, so APIs are subject to change until version 1.0.
|
||||
|
||||
We expect 1.0 to be at or before Q3 2022, so please practice the current APIs to ensure they work for you!
|
||||
We expect [wazero 1.0][9] to be at or before Q3 2022, so please practice the
|
||||
current APIs to ensure they work for you!
|
||||
|
||||
### Go
|
||||
|
||||
wazero has no dependencies except Go, so the only source of conflict in your project's use of Wazero is the Go version.
|
||||
wazero has no dependencies except Go, so the only source of conflict in your
|
||||
project's use of wazero is the Go version.
|
||||
|
||||
To simplify our support policy, we adopt Go's [Release Policy](https://go.dev/doc/devel/release) (two versions).
|
||||
To simplify our support policy, we adopt Go's [Release Policy][10] (two versions).
|
||||
|
||||
This means wazero will remain compilable and tested on the the version prior to the latest release of Go.
|
||||
This means wazero will remain compilable and tested on the version prior to the
|
||||
latest release of Go.
|
||||
|
||||
For example, once Go 1.29 is released, wazero may choose to use a Go 1.28 feature.
|
||||
For example, once Go 1.29 is released, wazero may use a Go 1.28 feature.
|
||||
|
||||
### Platform
|
||||
|
||||
@@ -135,7 +154,7 @@ systems are ones we test, but that doesn't necessarily mean other operating
|
||||
system versions won't work.
|
||||
|
||||
We currently test Linux (Ubuntu and scratch), MacOS and Windows as packaged by
|
||||
[GitHub Actions](https://github.com/actions/virtual-environments).
|
||||
[GitHub Actions][11].
|
||||
|
||||
* Interpreter
|
||||
* Linux is tested on amd64 (native) as well arm64 and riscv64 via emulation.
|
||||
@@ -148,99 +167,78 @@ wazero has no dependencies and doesn't require CGO. This means it can also be
|
||||
embedded in an application that doesn't use an operating system. This is a main
|
||||
differentiator between wazero and alternatives.
|
||||
|
||||
We verify wazero's independence by running tests in Docker's [scratch image](https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch).
|
||||
We verify zero dependencies by running tests in Docker's [scratch image][12].
|
||||
This approach ensures compatibility with any parent image.
|
||||
|
||||
## Standards Compliance
|
||||
## Specifications
|
||||
|
||||
wazero understands that while no-one desired to create confusion, confusion
|
||||
exists both in what is a standard and what in practice is in fact a standard
|
||||
feature. To help with this, we created some guidance both on the status quo
|
||||
of WebAssembly portability and what we support.
|
||||
|
||||
The [WebAssembly Core Specification 1.0 (20191205)](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205)
|
||||
is the only part of the WebAssembly ecosystem that is a W3C recommendation.
|
||||
The WebAssembly Core Specification is the only specification relevant to
|
||||
wazero, governed by a standards body. Release [1.0][1] is a Web Standard (REC).
|
||||
Release [2.0][2] is a Working Draft (WD), so not yet a Web Standard.
|
||||
|
||||
In practice, this specification is not enough. Most compilers that target Wasm
|
||||
rely on features that have not yet gone through W3C recommendation process,
|
||||
such as `bulk-memory-operations`.
|
||||
Many compilers implement system calls using the WebAssembly System Interface,
|
||||
[WASI][5]. WASI is a WebAssembly community [subgroup][4], but has not published
|
||||
any working drafts as a result of their work. WASI's last stable point was
|
||||
[wasi_snapshot_preview1][13], tagged at the end of 2020.
|
||||
|
||||
Also, most compilers implement system calls using the WebAssembly System
|
||||
Interface ([WASI](https://github.com/WebAssembly/WASI)). While WASI aims to be
|
||||
a common layer for portability, it is not governed by a standards body, like
|
||||
W3C. Moreover, while commonly implemented, WASI is not yet versioned. Its last
|
||||
stable point was the "wasi_snapshot_preview1" tag released at the end of 2020.
|
||||
|
||||
While this seems scary, the confusion caused by non-standard features and
|
||||
non-standard specifications is not as bad as it sounds. The WebAssembly
|
||||
ecosystem is generally responsive regardless of where things are written down
|
||||
and wazero provides tools, such as built-in support for WASI, to reduce pain.
|
||||
While this seems scary, the confusion caused by pre-standard features is not as
|
||||
bad as it sounds. The WebAssembly ecosystem is generally responsive regardless
|
||||
of where things are written down and wazero provides tools, such as built-in
|
||||
support for WASI, to reduce pain.
|
||||
|
||||
The goal of this section isn't to promote a W3C recommendation exclusive
|
||||
approach, rather to help you understand common language around portable
|
||||
features and which of those wazero supports at the moment. While we consider
|
||||
features formalized through W3C recommendation status mandatory, we actively
|
||||
pursue non-standard features as well interop with commonly used infrastructure
|
||||
pursue pre-standard features as well interop with commonly used infrastructure
|
||||
such as AssemblyScript.
|
||||
|
||||
In summary, we hope this section can guide you in terms of what wazero supports
|
||||
as well as how to classify a request for a feature we don't yet support.
|
||||
|
||||
### WebAssembly Core
|
||||
wazero supports the only WebAssembly specification which has reached W3C
|
||||
Recommendation (REC) phase: [WebAssembly Core Specification 1.0 (20191205)](https://www.w3.org/TR/2019/REC-wasm-core-1-20191205).
|
||||
|
||||
Independent verification is possible via the [WebAssembly spec test suite](https://github.com/WebAssembly/spec/tree/wg-1.0/test/core),
|
||||
which we run on every change and against all supported platforms.
|
||||
wazero conforms with spectests [7] defined alongside WebAssembly Core
|
||||
Specification [1.0][1]. There is also [work in progress][14] towards release
|
||||
[2.0][2], despite it not being a Web Standard, yet.
|
||||
|
||||
One current limitation of wazero is that it doesn't fully implement the Text
|
||||
Format, yet, e.g. compiling `.wat` files. The intent is to finish this, and
|
||||
meanwhile users can work around this using tools such as `wat2wasm` to compile
|
||||
the text format into the binary format.
|
||||
Format, yet, e.g. compiling `.wat` files. The intent is to [finish this][15],
|
||||
and meanwhile users can work around this using tools such as `wat2wasm` to
|
||||
compile the text format into the binary format. In practice, the text format is
|
||||
too low level for most users, so delays here have limited impact.
|
||||
|
||||
#### Post 1.0 Features
|
||||
#### Post 2.0 Features
|
||||
Features regardless of W3C release are inventoried in the [Proposals][16].
|
||||
repository. wazero implements [Finished Proposals][17] based on user demand,
|
||||
using [wazero.RuntimeConfig][18] feature flags.
|
||||
|
||||
The last W3C REC was at the end of 2019. There were other features that didn't
|
||||
make the cut or were developed in the years since. The community unofficially
|
||||
refers to these as [Finished Proposals](https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md).
|
||||
|
||||
To ensure compatability, wazero does not opt-in to any non-standard feature by
|
||||
default. However, the following status covers what's currently possible with
|
||||
`wazero.RuntimeConfig`.
|
||||
|
||||
| Feature | Status |
|
||||
|:-------------------------------------:|:------:|
|
||||
| mutable-global | ✅ |
|
||||
| nontrapping-float-to-int-conversions | ✅ |
|
||||
| sign-extension-ops | ✅ |
|
||||
| multi-value | ✅ |
|
||||
| JS-BigInt-integration | N/A |
|
||||
| reference-types | 👷♂️ |
|
||||
| bulk-memory-operations | ✅ |
|
||||
| simd | ❌ |
|
||||
|
||||
Note: While the above are specified in a WebAssembly GitHub repository, they
|
||||
are not W3C recommendations (standards). This means they can change further
|
||||
between now and any future update to the W3C WebAssembly core specification.
|
||||
Due to this, we cannot guarantee future compatability. Please encourage the
|
||||
[WebAssembly community](https://www.w3.org/community/webassembly/) to formalize
|
||||
features you rely on, specifically to reach the W3C recommendation (REC) phase.
|
||||
Features not yet assigned to a W3C release are not reliable. Encourage the
|
||||
[WebAssembly community][19] to formalize features you rely on, so that they
|
||||
become assigned to a release, and reach the W3C recommendation (REC) phase.
|
||||
|
||||
### WebAssembly System Interface (WASI)
|
||||
|
||||
As of early 2022, the WebAssembly System Interface (WASI) has never reached the
|
||||
recommendation phase of the W3C. The closest to stability is a draft ([snapshot-01](https://github.com/WebAssembly/WASI/tree/snapshot-01))
|
||||
released in late 2020. Some functions of this draft are used in practice while
|
||||
some features are not known to be used at all. Further confusion exists because
|
||||
some compilers (ex GrainLang) import functions not used. Finally, `snapshot-01`
|
||||
includes features such as "rights" that [will be removed](https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844).
|
||||
Many compilers implement system calls using the WebAssembly System Interface,
|
||||
[WASI][5]. WASI is a WebAssembly community [subgroup][4], but has not published
|
||||
any working drafts as a result of their work. WASI's last stable point was
|
||||
[wasi_snapshot_preview1][13], tagged at the end of 2020.
|
||||
|
||||
Some functions in this tag are used in practice while some others are not known
|
||||
to be used at all. Further confusion exists because some compilers, like
|
||||
GrainLang, import functions not used. Finally, [wasi_snapshot_preview1][13]
|
||||
includes features such as "rights" that [will be removed][20].
|
||||
|
||||
For all of these reasons, wazero will not implement all WASI features, just to
|
||||
complete the below chart. If you desire something not yet implemented, please
|
||||
[raise an issue](https://github.com/tetratelabs/wazero/issues/new) and include
|
||||
your use case (ex which language you are using to compile, a.k.a. target Wasm).
|
||||
|
||||
<details><summary>Click to see the full list of supported WASI systemcalls</summary>
|
||||
<details><summary>Click to see the full list of supported WASI functions</summary>
|
||||
<p>
|
||||
|
||||
| Function | Status | Known Usage |
|
||||
@@ -296,17 +294,16 @@ your use case (ex which language you are using to compile, a.k.a. target Wasm).
|
||||
|
||||
## History of wazero
|
||||
|
||||
wazero was originally developed by [Takeshi Yoneda](https://github.com/mathetake)
|
||||
as a hobby project in mid 2020. In late 2021, it was sponsored by Tetrate as a
|
||||
top-level project. That said, Takeshi's original motivation is as relevant
|
||||
today as when he started the project, and worthwhile reading:
|
||||
wazero was originally developed by [Takeshi Yoneda][21] as a hobby project in
|
||||
mid 2020. In late 2021, it was sponsored by Tetrate as a top-level project.
|
||||
That said, Takeshi's original motivation is as relevant today as when he
|
||||
started the project, and worthwhile reading:
|
||||
|
||||
If you want to provide Wasm host environments in your Go programs, currently
|
||||
there's no other choice than using CGO leveraging the state-of-the-art
|
||||
runtimes written in C++/Rust (e.g. V8, Wasmtime, Wasmer, WAVM, etc.), and
|
||||
there's no pure Go Wasm runtime out there. (There's only one exception named
|
||||
[wagon](https://github.com/go-interpreter/wagon), but it was archived with the
|
||||
mention to this project.)
|
||||
[wagon][22], but it was archived with the mention to this project.)
|
||||
|
||||
First, why do you want to write host environments in Go? You might want to have
|
||||
plugin systems in your Go project and want these plugin systems to be
|
||||
@@ -315,21 +312,47 @@ languages. That's where Wasm comes into play. You write your own Wasm host
|
||||
environments and embed Wasm runtime in your projects, and now users are able to
|
||||
write plugins in their own favorite languages (AssemblyScript, C, C++, Rust,
|
||||
Zig, etc.). As a specific example, you maybe write proxy severs in Go and want
|
||||
to allow users to extend the proxy via [Proxy-Wasm ABI](https://github.com/proxy-wasm/spec).
|
||||
Maybe you are writing server-side rendering applications via Wasm, or
|
||||
[OpenPolicyAgent](https://www.openpolicyagent.org/docs/latest/wasm/) is using
|
||||
Wasm for plugin system.
|
||||
to allow users to extend the proxy via [Proxy-Wasm ABI][23]. Maybe you are
|
||||
writing server-side rendering applications via Wasm, or [OpenPolicyAgent][24]
|
||||
is using Wasm for plugin system.
|
||||
|
||||
However, experienced Golang developers often avoid using CGO because it
|
||||
introduces complexity. For example, CGO projects are larger and complicated to
|
||||
consume due to their libc + shared library dependency. Debugging is more
|
||||
difficult for Go developers when most of a library is written in Rustlang.
|
||||
[_CGO is not Go_](https://dave.cheney.net/2016/01/18/cgo-is-not-go)[ -- _Rob_ _Pike_](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=757s) dives in deeper.
|
||||
In short, the primary motivation to start wazero was to avoid CGO.
|
||||
[_CGO is not Go_][25] [ -- _Rob_ _Pike_][26] dives in deeper. In short, the
|
||||
primary motivation to start wazero was to avoid CGO.
|
||||
|
||||
wazero compiles WebAssembly modules into native assembly (JIT) by default. You
|
||||
may be surprised to find equal or better performance vs mature JIT-style
|
||||
runtimes because [CGO is slow](https://github.com/golang/go/issues/19574). More
|
||||
specifically, if you make large amount of CGO calls which cross the boundary
|
||||
between Go and C (stack) space, then the usage of CGO could be a bottleneck.
|
||||
runtimes because [CGO is slow][27]. More specifically, if you make large amount
|
||||
of CGO calls which cross the boundary between Go and C (stack) space, then the
|
||||
usage of CGO could be a bottleneck.
|
||||
|
||||
[1]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
|
||||
[2]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/
|
||||
[3]: ./internal/integration_test/post1_0/multi-value/testdata/fac.wat
|
||||
[4]: https://github.com/WebAssembly/meetings/blob/main/process/subgroups.md
|
||||
[5]: https://github.com/WebAssembly/WASI
|
||||
[6]: https://pkg.go.dev/golang.org/x/sys/unix
|
||||
[7]: https://github.com/WebAssembly/spec/tree/wg-1.0/test/core
|
||||
[8]: ./internal/wasm/jit/RATIONALE.md
|
||||
[9]: https://github.com/tetratelabs/wazero/issues/506
|
||||
[10]: https://go.dev/doc/devel/release
|
||||
[11]: https://github.com/actions/virtual-environments
|
||||
[12]: https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch
|
||||
[13]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md
|
||||
[14]: https://github.com/tetratelabs/wazero/issues/484
|
||||
[15]: https://github.com/tetratelabs/wazero/issues/59
|
||||
[16]: https://github.com/WebAssembly/proposals
|
||||
[17]: https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md
|
||||
[18]: https://pkg.go.dev/github.com/tetratelabs/wazero#RuntimeConfig
|
||||
[19]: https://www.w3.org/community/webassembly/
|
||||
[20]: https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
|
||||
[21]: https://github.com/mathetake
|
||||
[22]: https://github.com/go-interpreter/wagon
|
||||
[23]: https://github.com/proxy-wasm/spec
|
||||
[24]: https://www.openpolicyagent.org/docs/latest/wasm/
|
||||
[25]: https://dave.cheney.net/2016/01/18/cgo-is-not-go
|
||||
[26]: https://www.youtube.com/watch?v=PAAkCSZUG1c&t=757s
|
||||
[27]: https://github.com/golang/go/issues/19574
|
||||
|
||||
35
internal/integration_test/vs/testdata/fac.wat
vendored
35
internal/integration_test/vs/testdata/fac.wat
vendored
@@ -1,35 +0,0 @@
|
||||
;; This includes a factorial function that uses the "multi-value" feature
|
||||
;;
|
||||
;; Compile like so, in order to not add any other post 1.0 features to the resulting wasm.
|
||||
;; wat2wasm \
|
||||
;; --disable-saturating-float-to-int \
|
||||
;; --disable-sign-extension \
|
||||
;; --disable-simd \
|
||||
;; --disable-bulk-memory \
|
||||
;; --disable-reference-types \
|
||||
;; --debug-names fac.wat
|
||||
;;
|
||||
;; See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
|
||||
(module
|
||||
(func $pick0 (param i64) (result i64 i64)
|
||||
(local.get 0) (local.get 0)
|
||||
)
|
||||
|
||||
(func $pick1 (param i64 i64) (result i64 i64 i64)
|
||||
(local.get 0) (local.get 1) (local.get 0)
|
||||
)
|
||||
|
||||
;; Note: This implementation loops forever if the input is zero.
|
||||
(func $fac (param i64) (result i64)
|
||||
(i64.const 1) (local.get 0)
|
||||
|
||||
(loop $l (param i64 i64) (result i64)
|
||||
(call $pick1) (call $pick1) (i64.mul)
|
||||
(call $pick1) (i64.const 1) (i64.sub)
|
||||
(call $pick0) (i64.const 0) (i64.gt_u)
|
||||
(br_if $l)
|
||||
(drop) (return)
|
||||
)
|
||||
)
|
||||
(export "fac" (func $fac))
|
||||
)
|
||||
Reference in New Issue
Block a user