Elaborates impact of GOWASM variable when compiling Go (#785)

Thanks to @inkeliz for the pointer!

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2022-08-31 12:21:34 +08:00
committed by GitHub
parent f95b95eecc
commit 8abe345249
12 changed files with 70 additions and 70 deletions

View File

@@ -40,8 +40,8 @@ type RuntimeConfig interface {
// due to the WebAssembly Working Group merging them "mutually dependent".
// Therefore, enabling this feature results in enabling WithFeatureReferenceTypes, and vice-versa.
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
// https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md and
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and
// https://github.com/WebAssembly/spec/pull/1287
WithFeatureBulkMemoryOperations(bool) RuntimeConfig
@@ -52,7 +52,7 @@ type RuntimeConfig interface {
// - Function (`func`) types allow more than one result
// - Block types (`block`, `loop` and `if`) can be arbitrary function types
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
WithFeatureMultiValue(bool) RuntimeConfig
// WithFeatureMutableGlobal allows globals to be mutable. This defaults to true as the feature was finished in
@@ -75,7 +75,7 @@ type RuntimeConfig interface {
// - `i64.trunc_sat_f64_s`
// - `i64.trunc_sat_f64_u`
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
WithFeatureNonTrappingFloatToIntConversion(bool) RuntimeConfig
// WithFeatureReferenceTypes enables various instructions and features related to table and new reference types.
@@ -98,8 +98,8 @@ type RuntimeConfig interface {
// due to the WebAssembly Working Group merging them "mutually dependent".
// Therefore, enabling this feature results in enabling WithFeatureBulkMemoryOperations, and vice-versa.
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
// https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md and
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md and
// https://github.com/WebAssembly/spec/pull/1287
WithFeatureReferenceTypes(enabled bool) RuntimeConfig
@@ -109,13 +109,13 @@ type RuntimeConfig interface {
// Here are the notable effects:
// - Adds instructions `i32.extend8_s`, `i32.extend16_s`, `i64.extend8_s`, `i64.extend16_s` and `i64.extend32_s`
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
WithFeatureSignExtensionOps(bool) RuntimeConfig
// WithFeatureSIMD enables the vector value type and vector instructions (aka SIMD). This defaults to false
// as the feature was not in WebAssembly 1.0.
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
WithFeatureSIMD(bool) RuntimeConfig
// WithWasmCore1 enables features included in the WebAssembly Core Specification 1.0. Selecting this

View File

@@ -28,7 +28,7 @@ import (
// - multiValueWasmFunctions
// - multiValueHostFunctions
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
func main() {
// Choose the context to use for function calls.
ctx := context.Background()

View File

@@ -1,22 +1,15 @@
# Overview
When `GOOS=js` and `GOARCH=wasm`, Go's compiler targets WebAssembly Binary
format (%.wasm).
Wazero's "github.com/tetratelabs/wazero/imports/go" package allows you to run
a `%.wasm` file compiled by Go. See https://wazero.io/languages/go/ for more.
a `%.wasm` file compiled by Go. This is similar to what is implemented in
[wasm_exec.js][1]. See https://wazero.io/languages/go/ for more.
## Usage
## Example
When `GOOS=js` and `GOARCH=wasm`, Go's compiler targets WebAssembly 1.0
Binary format (%.wasm).
Ex.
```bash
GOOS=js GOARCH=wasm go build -o cat.wasm .
```
After compiling `cat.wasm` with wazero.Runtime's `CompileModule`, Run it.
Under the scenes, the compiled Wasm calls host functions that support the
runtime.GOOS. This is similar to what is implemented in [wasm_exec.js][1].
wazero includes an [example](example) that makes HTTP client requests.
## Experimental

View File

@@ -5,14 +5,17 @@ this shows an interesting feature this supports, HTTP client requests.
```bash
$ cd stars
$ GOARCH=wasm GOOS=js go build -o main.wasm .
$ GOARCH=wasm GOOS=js GOWASM=satconv,signext go build -o main.wasm .
$ cd ..
$ go run stars.go
wazero has 9999999 stars. Does that include you?
```
Internally, this uses [gojs](../../experimental/gojs/gojs.go), which implements
the custom host functions required by Go.
Internally, this uses [gojs](../gojs.go), which implements the custom host
functions required by Go.
Note: `GOARCH=wasm GOOS=js` is experimental as is wazero's support of it. For
details, see https://wazero.io/languages/go/.
Notes:
* `GOARCH=wasm GOOS=js` is experimental as is wazero's support of it. For
details, see https://wazero.io/languages/go/.
* `GOWASM=satconv,signext` enables features in WebAssembly Core Specification
2.0.

View File

@@ -41,7 +41,7 @@ func compileFromGo() error {
cmd := exec.Command("go", "build", "-o", "main.wasm", ".")
cmd.Dir = "stars"
cmd.Env = append(os.Environ(), "GOARCH=wasm", "GOOS=js")
cmd.Env = append(os.Environ(), "GOARCH=wasm", "GOOS=js", "GOWASM=satconv,signext")
start := time.Now()
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("go build: %v\n%s", err, out)

View File

@@ -1,20 +1,5 @@
// Package gojs allows you to run wasm binaries compiled by Go when `GOOS=js`
// and `GOARCH=wasm`.
//
// # Usage
//
// When `GOOS=js` and `GOARCH=wasm`, Go's compiler targets WebAssembly 1.0
// Binary format (%.wasm).
//
// Ex.
//
// GOOS=js GOARCH=wasm go build -o cat.wasm .
//
// After compiling `cat.wasm` with wazero.Runtime's `CompileModule`, Run it.
//
// Under the scenes, the compiled Wasm calls host functions that support the
// runtime.GOOS. This is similar to what is implemented in wasm_exec.js. See
// https://github.com/golang/go/blob/go1.19/misc/wasm/wasm_exec.js
// and `GOARCH=wasm`. See https://wazero.io/languages/go/ for more.
//
// # Experimental
//
@@ -49,7 +34,7 @@ func WithRoundTripper(ctx context.Context, rt http.RoundTripper) context.Context
// # Parameters
//
// - ctx: context to use when instantiating the module and calling "run".
// - r: runtime to instantiate both the host and guest (compiled) module into.
// - r: runtime to instantiate both the host and guest (compiled) module in.
// - compiled: guest binary compiled with `GOARCH=wasm GOOS=js`
// - config: the configuration such as args, env or filesystem to use.
//
@@ -70,6 +55,8 @@ func WithRoundTripper(ctx context.Context, rt http.RoundTripper) context.Context
//
// # Notes
//
// - Use wazero.RuntimeConfig `WithWasmCore2` to avoid needing to pick >1.0
// features set by `GOWASM` or used internally by Run.
// - Wasm generated by `GOARCH=wasm GOOS=js` is very slow to compile.
// Use experimental.WithCompilationCacheDirName to improve performance.
// - Both the host and guest module are closed after being run.

View File

@@ -741,7 +741,7 @@ func (c *amd64Compiler) compileV128Bitselect(*wazeroir.OperationV128Bitselect) e
}
// The following logic is equivalent to v128.or(v128.and(v1, selector), v128.and(v2, v128.not(selector)))
// See https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#bitwise-select
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#bitwise-select
c.assembler.CompileRegisterToRegister(amd64.PAND, selector.register, x1.register)
c.assembler.CompileRegisterToRegister(amd64.PANDN, x2.register, selector.register)
c.assembler.CompileRegisterToRegister(amd64.POR, selector.register, x1.register)

View File

@@ -2430,7 +2430,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont
}
frame.pc++
case wazeroir.OperationKindV128BitMask:
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#bitmask-extraction
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#bitmask-extraction
hi, lo := ce.popValue(), ce.popValue()
var res uint64
switch op.b1 {
@@ -2501,7 +2501,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont
ce.pushValue(x1Hi ^ x2Hi)
frame.pc++
case wazeroir.OperationKindV128Bitselect:
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#bitwise-select
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#bitwise-select
cHi, cLo := ce.popValue(), ce.popValue()
x2Hi, x2Lo := ce.popValue(), ce.popValue()
x1Hi, x1Lo := ce.popValue(), ce.popValue()
@@ -3017,7 +3017,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont
var retLo, retHi uint64
// Lane-wise addition while saturating the overflowing values.
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#saturating-integer-addition
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#saturating-integer-addition
switch op.b1 {
case wazeroir.ShapeI8x16:
for i := 0; i < 16; i++ {
@@ -3099,7 +3099,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont
var retLo, retHi uint64
// Lane-wise subtraction while saturating the overflowing values.
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#saturating-integer-subtraction
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#saturating-integer-subtraction
switch op.b1 {
case wazeroir.ShapeI8x16:
for i := 0; i < 16; i++ {
@@ -3777,7 +3777,7 @@ func (ce *callEngine) callNativeFunc(ctx context.Context, callCtx *wasm.CallCont
}
var uv uint64
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#saturating-integer-q-format-rounding-multiplication
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#saturating-integer-q-format-rounding-multiplication
if calc := ((int32(v) * int32(w)) + 0x4000) >> 15; calc < math.MinInt16 {
uv = uint64(uint16(0x8000))
} else if calc > math.MaxInt16 {
@@ -4190,12 +4190,12 @@ func flt64(z1, z2 float64) bool {
}
func i8RoundingAverage(v1, v2 byte) byte {
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#lane-wise-integer-rounding-average
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#lane-wise-integer-rounding-average
return byte((uint16(v1) + uint16(v2) + uint16(1)) / 2)
}
func i16RoundingAverage(v1, v2 uint16) uint16 {
// https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#lane-wise-integer-rounding-average
// https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md#lane-wise-integer-rounding-average
return uint16((uint32(v1) + uint32(v2) + 1) / 2)
}

View File

@@ -83,7 +83,7 @@ func TestMain(m *testing.M) {
// Seed wazero's compilation cache to see any error up-front and to prevent
// one test from a cache-miss performance penalty.
rt := wazero.NewRuntime(testCtx)
rt := wazero.NewRuntimeWithConfig(testCtx, wazero.NewRuntimeConfig().WithWasmCore2())
defer rt.Close(testCtx)
_, err = rt.CompileModule(testCtx, testBin, wazero.NewCompileConfig())
if err != nil {
@@ -117,7 +117,7 @@ func compileJsWasm(goBin string) error {
bin := path.Join(workDir, "out.wasm")
cmd := exec.CommandContext(ctx, goBin, "build", "-o", bin, ".") //nolint:gosec
cmd.Env = append(os.Environ(), "GOOS=js", "GOARCH=wasm")
cmd.Env = append(os.Environ(), "GOOS=js", "GOARCH=wasm", "GOWASM=satconv,signext")
cmd.Dir = "testdata"
out, err := cmd.CombinedOutput()
if err != nil {

View File

@@ -47,7 +47,7 @@ const (
// * FunctionType.Results length greater than one.
// * `block`, `loop` and `if` can be arbitrary function types.
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
FeatureMultiValue
// FeatureMutableGlobal decides if global vars are allowed to be imported or exported (ExternTypeGlobal)
@@ -65,7 +65,7 @@ const (
// * [ OpcodeMiscPrefix, OpcodeMiscI64TruncSatF64S]
// * [ OpcodeMiscPrefix, OpcodeMiscI64TruncSatF64U]
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
FeatureNonTrappingFloatToIntConversion
// FeatureReferenceTypes enables various features related to reference types and tables.
@@ -83,7 +83,7 @@ const (
// * OpcodeCallIndirect, OpcodeTableInit, and OpcodeElemDrop can take non-zero table indexes.
// * Element segments can take non-zero table index.
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md
FeatureReferenceTypes
// FeatureSignExtensionOps decides if parsing should succeed on the following instructions:
@@ -94,12 +94,12 @@ const (
// * OpcodeI64Extend16S
// * OpcodeI64Extend32S
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
FeatureSignExtensionOps
// FeatureSIMD enables the vector value type and vector instructions.
//
// See https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
FeatureSIMD
)
@@ -147,22 +147,22 @@ func featureName(f Features) string {
// match https://github.com/WebAssembly/mutable-global
return "mutable-global"
case FeatureSignExtensionOps:
// match https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
return "sign-extension-ops"
case FeatureMultiValue:
// match https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
return "multi-value"
case FeatureNonTrappingFloatToIntConversion:
// match https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
return "nontrapping-float-to-int-conversion"
case FeatureBulkMemoryOperations:
// match https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/bulk-memory-operations/Overview.md
return "bulk-memory-operations"
case FeatureReferenceTypes:
// match https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/reference-types/Overview.md
return "reference-types"
case FeatureSIMD:
// match https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
// match https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/simd/SIMD.md
return "simd"
}
return ""

View File

@@ -1847,7 +1847,7 @@ type controlBlock struct {
// FeatureMultiValue and include an index in the Module.TypeSection.
//
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-blocktype
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
// See https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/multi-value/Overview.md
func DecodeBlockType(types []*FunctionType, r *bytes.Reader, enabledFeatures Features) (*FunctionType, uint64, error) {
raw, num, err := leb128.DecodeInt33AsInt64(r)
if err != nil {

View File

@@ -4,8 +4,8 @@ title = "Go"
## Introduction
When `GOARCH=wasm GOOS=js`, Go's compiler targets WebAssembly 1.0 Binary
format (%.wasm).
When `GOARCH=wasm GOOS=js`, Go's compiler targets WebAssembly Binary format
(%.wasm).
Ex.
```bash
@@ -34,6 +34,18 @@ Due to lack of adoption, support and relatively high implementation overhead,
most choose [TinyGo](tinygo) to compile source code, even if it supports less
features.
## WebAssembly Features
`GOARCH=wasm GOOS=js` uses instructions in [WebAssembly Core Specification 1.0]
[15] unless `GOWASM` includes features added afterwards.
Here are the valid [GOWASM values][16]:
* `satconv` - [Non-trapping Float-to-int Conversions][17]
* `signext` - [Sign-extension operators][18]
Note that both the above features are included [working draft][19] of
WebAssembly Core Specification 2.0.
## Constraints
Please read our overview of WebAssembly and
@@ -243,3 +255,8 @@ the Go stack.
[12]: https://github.com/golang/go/blob/go1.19/src/cmd/link/internal/ld/data.go#L2457
[13]: https://github.com/golang/go/blob/go1.19/src/syscall/tables_js.go#L371-L494
[14]: https://github.com/tetratelabs/wazero/tree/main/imports/go/example
[15]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/
[16]: https://github.com/golang/go/blob/go1.19/src/internal/buildcfg/cfg.go#L133-L147
[17]: https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/nontrapping-float-to-int-conversion/Overview.md
[18]: https://github.com/WebAssembly/spec/blob/wg-2.0.draft1/proposals/sign-extension-ops/Overview.md
[19]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/