summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/internal/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/internal/wasm')
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go100
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go105
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go22
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go79
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go193
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go269
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go11
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go32
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go56
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go50
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go9
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go52
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go47
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go42
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go151
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go226
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go43
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go59
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go51
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go76
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go2336
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go188
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/global.go55
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go279
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/host.go179
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go1866
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go476
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go128
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/module.go1078
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go251
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go73
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/store.go679
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go95
-rw-r--r--vendor/github.com/tetratelabs/wazero/internal/wasm/table.go339
34 files changed, 0 insertions, 9695 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go
deleted file mode 100644
index 2fac9196c..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/code.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
- "io"
- "math"
-
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeCode(r *bytes.Reader, codeSectionStart uint64, ret *wasm.Code) (err error) {
- ss, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("get the size of code: %w", err)
- }
- remaining := int64(ss)
-
- // Parse #locals.
- ls, bytesRead, err := leb128.DecodeUint32(r)
- remaining -= int64(bytesRead)
- if err != nil {
- return fmt.Errorf("get the size locals: %v", err)
- } else if remaining < 0 {
- return io.EOF
- }
-
- // Validate the locals.
- bytesRead = 0
- var sum uint64
- for i := uint32(0); i < ls; i++ {
- num, n, err := leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("read n of locals: %v", err)
- } else if remaining < 0 {
- return io.EOF
- }
-
- sum += uint64(num)
-
- b, err := r.ReadByte()
- if err != nil {
- return fmt.Errorf("read type of local: %v", err)
- }
-
- bytesRead += n + 1
- switch vt := b; vt {
- case wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeI64, wasm.ValueTypeF64,
- wasm.ValueTypeFuncref, wasm.ValueTypeExternref, wasm.ValueTypeV128:
- default:
- return fmt.Errorf("invalid local type: 0x%x", vt)
- }
- }
-
- if sum > math.MaxUint32 {
- return fmt.Errorf("too many locals: %d", sum)
- }
-
- // Rewind the buffer.
- _, err = r.Seek(-int64(bytesRead), io.SeekCurrent)
- if err != nil {
- return err
- }
-
- localTypes := make([]wasm.ValueType, 0, sum)
- for i := uint32(0); i < ls; i++ {
- num, bytesRead, err := leb128.DecodeUint32(r)
- remaining -= int64(bytesRead) + 1 // +1 for the subsequent ReadByte
- if err != nil {
- return fmt.Errorf("read n of locals: %v", err)
- } else if remaining < 0 {
- return io.EOF
- }
-
- b, err := r.ReadByte()
- if err != nil {
- return fmt.Errorf("read type of local: %v", err)
- }
-
- for j := uint32(0); j < num; j++ {
- localTypes = append(localTypes, b)
- }
- }
-
- bodyOffsetInCodeSection := codeSectionStart - uint64(r.Len())
- body := make([]byte, remaining)
- if _, err = io.ReadFull(r, body); err != nil {
- return fmt.Errorf("read body: %w", err)
- }
-
- if endIndex := len(body) - 1; endIndex < 0 || body[endIndex] != wasm.OpcodeEnd {
- return fmt.Errorf("expr not end with OpcodeEnd")
- }
-
- ret.BodyOffsetInCodeSection = bodyOffsetInCodeSection
- ret.LocalTypes = localTypes
- ret.Body = body
- return nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go
deleted file mode 100644
index edfc0a086..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/const_expr.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
- "io"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/ieee754"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeConstantExpression(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.ConstantExpression) error {
- b, err := r.ReadByte()
- if err != nil {
- return fmt.Errorf("read opcode: %v", err)
- }
-
- remainingBeforeData := int64(r.Len())
- offsetAtData := r.Size() - remainingBeforeData
-
- opcode := b
- switch opcode {
- case wasm.OpcodeI32Const:
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- _, _, err = leb128.DecodeInt32(r)
- case wasm.OpcodeI64Const:
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- _, _, err = leb128.DecodeInt64(r)
- case wasm.OpcodeF32Const:
- buf := make([]byte, 4)
- if _, err := io.ReadFull(r, buf); err != nil {
- return fmt.Errorf("read f32 constant: %v", err)
- }
- _, err = ieee754.DecodeFloat32(buf)
- case wasm.OpcodeF64Const:
- buf := make([]byte, 8)
- if _, err := io.ReadFull(r, buf); err != nil {
- return fmt.Errorf("read f64 constant: %v", err)
- }
- _, err = ieee754.DecodeFloat64(buf)
- case wasm.OpcodeGlobalGet:
- _, _, err = leb128.DecodeUint32(r)
- case wasm.OpcodeRefNull:
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
- return fmt.Errorf("ref.null is not supported as %w", err)
- }
- reftype, err := r.ReadByte()
- if err != nil {
- return fmt.Errorf("read reference type for ref.null: %w", err)
- } else if reftype != wasm.RefTypeFuncref && reftype != wasm.RefTypeExternref {
- return fmt.Errorf("invalid type for ref.null: 0x%x", reftype)
- }
- case wasm.OpcodeRefFunc:
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
- return fmt.Errorf("ref.func is not supported as %w", err)
- }
- // Parsing index.
- _, _, err = leb128.DecodeUint32(r)
- case wasm.OpcodeVecPrefix:
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil {
- return fmt.Errorf("vector instructions are not supported as %w", err)
- }
- opcode, err = r.ReadByte()
- if err != nil {
- return fmt.Errorf("read vector instruction opcode suffix: %w", err)
- }
-
- if opcode != wasm.OpcodeVecV128Const {
- return fmt.Errorf("invalid vector opcode for const expression: %#x", opcode)
- }
-
- remainingBeforeData = int64(r.Len())
- offsetAtData = r.Size() - remainingBeforeData
-
- n, err := r.Read(make([]byte, 16))
- if err != nil {
- return fmt.Errorf("read vector const instruction immediates: %w", err)
- } else if n != 16 {
- return fmt.Errorf("read vector const instruction immediates: needs 16 bytes but was %d bytes", n)
- }
- default:
- return fmt.Errorf("%v for const expression opt code: %#x", ErrInvalidByte, b)
- }
-
- if err != nil {
- return fmt.Errorf("read value: %v", err)
- }
-
- if b, err = r.ReadByte(); err != nil {
- return fmt.Errorf("look for end opcode: %v", err)
- }
-
- if b != wasm.OpcodeEnd {
- return fmt.Errorf("constant expression has been not terminated")
- }
-
- ret.Data = make([]byte, remainingBeforeData-int64(r.Len())-1)
- if _, err = r.ReadAt(ret.Data, offsetAtData); err != nil {
- return fmt.Errorf("error re-buffering ConstantExpression.Data")
- }
- ret.Opcode = opcode
- return nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go
deleted file mode 100644
index 771f8c327..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/custom.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package binary
-
-import (
- "bytes"
-
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-// decodeCustomSection deserializes the data **not** associated with the "name" key in SectionIDCustom.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0
-func decodeCustomSection(r *bytes.Reader, name string, limit uint64) (result *wasm.CustomSection, err error) {
- buf := make([]byte, limit)
- _, err = r.Read(buf)
-
- result = &wasm.CustomSection{
- Name: name,
- Data: buf,
- }
-
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go
deleted file mode 100644
index 054ccb3c6..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/data.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
- "io"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-// dataSegmentPrefix represents three types of data segments.
-//
-// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
-type dataSegmentPrefix = uint32
-
-const (
- // dataSegmentPrefixActive is the prefix for the version 1.0 compatible data segment, which is classified as "active" in 2.0.
- dataSegmentPrefixActive dataSegmentPrefix = 0x0
- // dataSegmentPrefixPassive prefixes the "passive" data segment as in version 2.0 specification.
- dataSegmentPrefixPassive dataSegmentPrefix = 0x1
- // dataSegmentPrefixActiveWithMemoryIndex is the active prefix with memory index encoded which is defined for futur use as of 2.0.
- dataSegmentPrefixActiveWithMemoryIndex dataSegmentPrefix = 0x2
-)
-
-func decodeDataSegment(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.DataSegment) (err error) {
- dataSegmentPrefx, _, err := leb128.DecodeUint32(r)
- if err != nil {
- err = fmt.Errorf("read data segment prefix: %w", err)
- return
- }
-
- if dataSegmentPrefx != dataSegmentPrefixActive {
- if err = enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
- err = fmt.Errorf("non-zero prefix for data segment is invalid as %w", err)
- return
- }
- }
-
- switch dataSegmentPrefx {
- case dataSegmentPrefixActive,
- dataSegmentPrefixActiveWithMemoryIndex:
- // Active data segment as in
- // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
- if dataSegmentPrefx == 0x2 {
- d, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("read memory index: %v", err)
- } else if d != 0 {
- return fmt.Errorf("memory index must be zero but was %d", d)
- }
- }
-
- err = decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpression)
- if err != nil {
- return fmt.Errorf("read offset expression: %v", err)
- }
- case dataSegmentPrefixPassive:
- // Passive data segment doesn't need const expr nor memory index encoded.
- // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-section
- ret.Passive = true
- default:
- err = fmt.Errorf("invalid data segment prefix: 0x%x", dataSegmentPrefx)
- return
- }
-
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- err = fmt.Errorf("get the size of vector: %v", err)
- return
- }
-
- ret.Init = make([]byte, vs)
- if _, err = io.ReadFull(r, ret.Init); err != nil {
- err = fmt.Errorf("read bytes for init: %v", err)
- }
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go
deleted file mode 100644
index c4191dae9..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/decoder.go
+++ /dev/null
@@ -1,193 +0,0 @@
-package binary
-
-import (
- "bytes"
- "debug/dwarf"
- "errors"
- "fmt"
- "io"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
- "github.com/tetratelabs/wazero/internal/wasmdebug"
-)
-
-// DecodeModule implements wasm.DecodeModule for the WebAssembly 1.0 (20191205) Binary Format
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-format%E2%91%A0
-func DecodeModule(
- binary []byte,
- enabledFeatures api.CoreFeatures,
- memoryLimitPages uint32,
- memoryCapacityFromMax,
- dwarfEnabled, storeCustomSections bool,
-) (*wasm.Module, error) {
- r := bytes.NewReader(binary)
-
- // Magic number.
- buf := make([]byte, 4)
- if _, err := io.ReadFull(r, buf); err != nil || !bytes.Equal(buf, Magic) {
- return nil, ErrInvalidMagicNumber
- }
-
- // Version.
- if _, err := io.ReadFull(r, buf); err != nil || !bytes.Equal(buf, version) {
- return nil, ErrInvalidVersion
- }
-
- memSizer := newMemorySizer(memoryLimitPages, memoryCapacityFromMax)
-
- m := &wasm.Module{}
- var info, line, str, abbrev, ranges []byte // For DWARF Data.
- for {
- // TODO: except custom sections, all others are required to be in order, but we aren't checking yet.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#modules%E2%91%A0%E2%93%AA
- sectionID, err := r.ReadByte()
- if err == io.EOF {
- break
- } else if err != nil {
- return nil, fmt.Errorf("read section id: %w", err)
- }
-
- sectionSize, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of section %s: %v", wasm.SectionIDName(sectionID), err)
- }
-
- sectionContentStart := r.Len()
- switch sectionID {
- case wasm.SectionIDCustom:
- // First, validate the section and determine if the section for this name has already been set
- name, nameSize, decodeErr := decodeUTF8(r, "custom section name")
- if decodeErr != nil {
- err = decodeErr
- break
- } else if sectionSize < nameSize {
- err = fmt.Errorf("malformed custom section %s", name)
- break
- } else if name == "name" && m.NameSection != nil {
- err = fmt.Errorf("redundant custom section %s", name)
- break
- }
-
- // Now, either decode the NameSection or CustomSection
- limit := sectionSize - nameSize
-
- var c *wasm.CustomSection
- if name != "name" {
- if storeCustomSections || dwarfEnabled {
- c, err = decodeCustomSection(r, name, uint64(limit))
- if err != nil {
- return nil, fmt.Errorf("failed to read custom section name[%s]: %w", name, err)
- }
- m.CustomSections = append(m.CustomSections, c)
- if dwarfEnabled {
- switch name {
- case ".debug_info":
- info = c.Data
- case ".debug_line":
- line = c.Data
- case ".debug_str":
- str = c.Data
- case ".debug_abbrev":
- abbrev = c.Data
- case ".debug_ranges":
- ranges = c.Data
- }
- }
- } else {
- if _, err = io.CopyN(io.Discard, r, int64(limit)); err != nil {
- return nil, fmt.Errorf("failed to skip name[%s]: %w", name, err)
- }
- }
- } else {
- m.NameSection, err = decodeNameSection(r, uint64(limit))
- }
- case wasm.SectionIDType:
- m.TypeSection, err = decodeTypeSection(enabledFeatures, r)
- case wasm.SectionIDImport:
- m.ImportSection, m.ImportPerModule, m.ImportFunctionCount, m.ImportGlobalCount, m.ImportMemoryCount, m.ImportTableCount, err = decodeImportSection(r, memSizer, memoryLimitPages, enabledFeatures)
- if err != nil {
- return nil, err // avoid re-wrapping the error.
- }
- case wasm.SectionIDFunction:
- m.FunctionSection, err = decodeFunctionSection(r)
- case wasm.SectionIDTable:
- m.TableSection, err = decodeTableSection(r, enabledFeatures)
- case wasm.SectionIDMemory:
- m.MemorySection, err = decodeMemorySection(r, enabledFeatures, memSizer, memoryLimitPages)
- case wasm.SectionIDGlobal:
- if m.GlobalSection, err = decodeGlobalSection(r, enabledFeatures); err != nil {
- return nil, err // avoid re-wrapping the error.
- }
- case wasm.SectionIDExport:
- m.ExportSection, m.Exports, err = decodeExportSection(r)
- case wasm.SectionIDStart:
- if m.StartSection != nil {
- return nil, errors.New("multiple start sections are invalid")
- }
- m.StartSection, err = decodeStartSection(r)
- case wasm.SectionIDElement:
- m.ElementSection, err = decodeElementSection(r, enabledFeatures)
- case wasm.SectionIDCode:
- m.CodeSection, err = decodeCodeSection(r)
- case wasm.SectionIDData:
- m.DataSection, err = decodeDataSection(r, enabledFeatures)
- case wasm.SectionIDDataCount:
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
- return nil, fmt.Errorf("data count section not supported as %v", err)
- }
- m.DataCountSection, err = decodeDataCountSection(r)
- default:
- err = ErrInvalidSectionID
- }
-
- readBytes := sectionContentStart - r.Len()
- if err == nil && int(sectionSize) != readBytes {
- err = fmt.Errorf("invalid section length: expected to be %d but got %d", sectionSize, readBytes)
- }
-
- if err != nil {
- return nil, fmt.Errorf("section %s: %v", wasm.SectionIDName(sectionID), err)
- }
- }
-
- if dwarfEnabled {
- d, _ := dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str)
- m.DWARFLines = wasmdebug.NewDWARFLines(d)
- }
-
- functionCount, codeCount := m.SectionElementCount(wasm.SectionIDFunction), m.SectionElementCount(wasm.SectionIDCode)
- if functionCount != codeCount {
- return nil, fmt.Errorf("function and code section have inconsistent lengths: %d != %d", functionCount, codeCount)
- }
- return m, nil
-}
-
-// memorySizer derives min, capacity and max pages from decoded wasm.
-type memorySizer func(minPages uint32, maxPages *uint32) (min uint32, capacity uint32, max uint32)
-
-// newMemorySizer sets capacity to minPages unless max is defined and
-// memoryCapacityFromMax is true.
-func newMemorySizer(memoryLimitPages uint32, memoryCapacityFromMax bool) memorySizer {
- return func(minPages uint32, maxPages *uint32) (min, capacity, max uint32) {
- if maxPages != nil {
- if memoryCapacityFromMax {
- return minPages, *maxPages, *maxPages
- }
- // This is an invalid value: let it propagate, we will fail later.
- if *maxPages > wasm.MemoryLimitPages {
- return minPages, minPages, *maxPages
- }
- // This is a valid value, but it goes over the run-time limit: return the limit.
- if *maxPages > memoryLimitPages {
- return minPages, minPages, memoryLimitPages
- }
- return minPages, minPages, *maxPages
- }
- if memoryCapacityFromMax {
- return minPages, memoryLimitPages, memoryLimitPages
- }
- return minPages, minPages, memoryLimitPages
- }
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go
deleted file mode 100644
index 7ab4b48eb..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/element.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package binary
-
-import (
- "bytes"
- "errors"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func ensureElementKindFuncRef(r *bytes.Reader) error {
- elemKind, err := r.ReadByte()
- if err != nil {
- return fmt.Errorf("read element prefix: %w", err)
- }
- if elemKind != 0x0 { // ElemKind is fixed to 0x0 now: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#element-section
- return fmt.Errorf("element kind must be zero but was 0x%x", elemKind)
- }
- return nil
-}
-
-func decodeElementInitValueVector(r *bytes.Reader) ([]wasm.Index, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- vec := make([]wasm.Index, vs)
- for i := range vec {
- u32, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("read function index: %w", err)
- }
-
- if u32 >= wasm.MaximumFunctionIndex {
- return nil, fmt.Errorf("too large function index in Element init: %d", u32)
- }
- vec[i] = u32
- }
- return vec, nil
-}
-
-func decodeElementConstExprVector(r *bytes.Reader, elemType wasm.RefType, enabledFeatures api.CoreFeatures) ([]wasm.Index, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("failed to get the size of constexpr vector: %w", err)
- }
- vec := make([]wasm.Index, vs)
- for i := range vec {
- var expr wasm.ConstantExpression
- err := decodeConstantExpression(r, enabledFeatures, &expr)
- if err != nil {
- return nil, err
- }
- switch expr.Opcode {
- case wasm.OpcodeRefFunc:
- if elemType != wasm.RefTypeFuncref {
- return nil, fmt.Errorf("element type mismatch: want %s, but constexpr has funcref", wasm.RefTypeName(elemType))
- }
- v, _, _ := leb128.LoadUint32(expr.Data)
- if v >= wasm.MaximumFunctionIndex {
- return nil, fmt.Errorf("too large function index in Element init: %d", v)
- }
- vec[i] = v
- case wasm.OpcodeRefNull:
- if elemType != expr.Data[0] {
- return nil, fmt.Errorf("element type mismatch: want %s, but constexpr has %s",
- wasm.RefTypeName(elemType), wasm.RefTypeName(expr.Data[0]))
- }
- vec[i] = wasm.ElementInitNullReference
- case wasm.OpcodeGlobalGet:
- i32, _, _ := leb128.LoadInt32(expr.Data)
- // Resolving the reference type from globals is done at instantiation phase. See the comment on
- // wasm.elementInitImportedGlobalReferenceType.
- vec[i] = wasm.WrapGlobalIndexAsElementInit(wasm.Index(i32))
- default:
- return nil, fmt.Errorf("const expr must be either ref.null or ref.func but was %s", wasm.InstructionName(expr.Opcode))
- }
- }
- return vec, nil
-}
-
-func decodeElementRefType(r *bytes.Reader) (ret wasm.RefType, err error) {
- ret, err = r.ReadByte()
- if err != nil {
- err = fmt.Errorf("read element ref type: %w", err)
- return
- }
- if ret != wasm.RefTypeFuncref && ret != wasm.RefTypeExternref {
- return 0, errors.New("ref type must be funcref or externref for element as of WebAssembly 2.0")
- }
- return
-}
-
-const (
- // The prefix is explained at https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#element-section
-
- // elementSegmentPrefixLegacy is the legacy prefix and is only valid one before CoreFeatureBulkMemoryOperations.
- elementSegmentPrefixLegacy = iota
- // elementSegmentPrefixPassiveFuncrefValueVector is the passive element whose indexes are encoded as vec(varint), and reftype is fixed to funcref.
- elementSegmentPrefixPassiveFuncrefValueVector
- // elementSegmentPrefixActiveFuncrefValueVectorWithTableIndex is the same as elementSegmentPrefixPassiveFuncrefValueVector but active and table index is encoded.
- elementSegmentPrefixActiveFuncrefValueVectorWithTableIndex
- // elementSegmentPrefixDeclarativeFuncrefValueVector is the same as elementSegmentPrefixPassiveFuncrefValueVector but declarative.
- elementSegmentPrefixDeclarativeFuncrefValueVector
- // elementSegmentPrefixActiveFuncrefConstExprVector is active whoce reftype is fixed to funcref and indexes are encoded as vec(const_expr).
- elementSegmentPrefixActiveFuncrefConstExprVector
- // elementSegmentPrefixPassiveConstExprVector is passive whoce indexes are encoded as vec(const_expr), and reftype is encoded.
- elementSegmentPrefixPassiveConstExprVector
- // elementSegmentPrefixPassiveConstExprVector is active whoce indexes are encoded as vec(const_expr), and reftype and table index are encoded.
- elementSegmentPrefixActiveConstExprVector
- // elementSegmentPrefixDeclarativeConstExprVector is declarative whoce indexes are encoded as vec(const_expr), and reftype is encoded.
- elementSegmentPrefixDeclarativeConstExprVector
-)
-
-func decodeElementSegment(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.ElementSegment) error {
- prefix, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("read element prefix: %w", err)
- }
-
- if prefix != elementSegmentPrefixLegacy {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
- return fmt.Errorf("non-zero prefix for element segment is invalid as %w", err)
- }
- }
-
- // Encoding depends on the prefix and described at https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#element-section
- switch prefix {
- case elementSegmentPrefixLegacy:
- // Legacy prefix which is WebAssembly 1.0 compatible.
- err = decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr)
- if err != nil {
- return fmt.Errorf("read expr for offset: %w", err)
- }
-
- ret.Init, err = decodeElementInitValueVector(r)
- if err != nil {
- return err
- }
-
- ret.Mode = wasm.ElementModeActive
- ret.Type = wasm.RefTypeFuncref
- return nil
- case elementSegmentPrefixPassiveFuncrefValueVector:
- // Prefix 1 requires funcref.
- if err = ensureElementKindFuncRef(r); err != nil {
- return err
- }
-
- ret.Init, err = decodeElementInitValueVector(r)
- if err != nil {
- return err
- }
- ret.Mode = wasm.ElementModePassive
- ret.Type = wasm.RefTypeFuncref
- return nil
- case elementSegmentPrefixActiveFuncrefValueVectorWithTableIndex:
- ret.TableIndex, _, err = leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("get size of vector: %w", err)
- }
-
- if ret.TableIndex != 0 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("table index must be zero but was %d: %w", ret.TableIndex, err)
- }
- }
-
- err := decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr)
- if err != nil {
- return fmt.Errorf("read expr for offset: %w", err)
- }
-
- // Prefix 2 requires funcref.
- if err = ensureElementKindFuncRef(r); err != nil {
- return err
- }
-
- ret.Init, err = decodeElementInitValueVector(r)
- if err != nil {
- return err
- }
-
- ret.Mode = wasm.ElementModeActive
- ret.Type = wasm.RefTypeFuncref
- return nil
- case elementSegmentPrefixDeclarativeFuncrefValueVector:
- // Prefix 3 requires funcref.
- if err = ensureElementKindFuncRef(r); err != nil {
- return err
- }
- ret.Init, err = decodeElementInitValueVector(r)
- if err != nil {
- return err
- }
- ret.Type = wasm.RefTypeFuncref
- ret.Mode = wasm.ElementModeDeclarative
- return nil
- case elementSegmentPrefixActiveFuncrefConstExprVector:
- err := decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr)
- if err != nil {
- return fmt.Errorf("read expr for offset: %w", err)
- }
-
- ret.Init, err = decodeElementConstExprVector(r, wasm.RefTypeFuncref, enabledFeatures)
- if err != nil {
- return err
- }
- ret.Mode = wasm.ElementModeActive
- ret.Type = wasm.RefTypeFuncref
- return nil
- case elementSegmentPrefixPassiveConstExprVector:
- ret.Type, err = decodeElementRefType(r)
- if err != nil {
- return err
- }
- ret.Init, err = decodeElementConstExprVector(r, ret.Type, enabledFeatures)
- if err != nil {
- return err
- }
- ret.Mode = wasm.ElementModePassive
- return nil
- case elementSegmentPrefixActiveConstExprVector:
- ret.TableIndex, _, err = leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("get size of vector: %w", err)
- }
-
- if ret.TableIndex != 0 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("table index must be zero but was %d: %w", ret.TableIndex, err)
- }
- }
- err := decodeConstantExpression(r, enabledFeatures, &ret.OffsetExpr)
- if err != nil {
- return fmt.Errorf("read expr for offset: %w", err)
- }
-
- ret.Type, err = decodeElementRefType(r)
- if err != nil {
- return err
- }
-
- ret.Init, err = decodeElementConstExprVector(r, ret.Type, enabledFeatures)
- if err != nil {
- return err
- }
-
- ret.Mode = wasm.ElementModeActive
- return nil
- case elementSegmentPrefixDeclarativeConstExprVector:
- ret.Type, err = decodeElementRefType(r)
- if err != nil {
- return err
- }
- ret.Init, err = decodeElementConstExprVector(r, ret.Type, enabledFeatures)
- if err != nil {
- return err
- }
-
- ret.Mode = wasm.ElementModeDeclarative
- return nil
- default:
- return fmt.Errorf("invalid element segment prefix: 0x%x", prefix)
- }
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go
deleted file mode 100644
index b9125b038..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/errors.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package binary
-
-import "errors"
-
-var (
- ErrInvalidByte = errors.New("invalid byte")
- ErrInvalidMagicNumber = errors.New("invalid magic number")
- ErrInvalidVersion = errors.New("invalid version header")
- ErrInvalidSectionID = errors.New("invalid section id")
- ErrCustomSectionNotFound = errors.New("custom section not found")
-)
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go
deleted file mode 100644
index 925e9c499..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/export.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeExport(r *bytes.Reader, ret *wasm.Export) (err error) {
- if ret.Name, _, err = decodeUTF8(r, "export name"); err != nil {
- return
- }
-
- b, err := r.ReadByte()
- if err != nil {
- err = fmt.Errorf("error decoding export kind: %w", err)
- return
- }
-
- ret.Type = b
- switch ret.Type {
- case wasm.ExternTypeFunc, wasm.ExternTypeTable, wasm.ExternTypeMemory, wasm.ExternTypeGlobal:
- if ret.Index, _, err = leb128.DecodeUint32(r); err != nil {
- err = fmt.Errorf("error decoding export index: %w", err)
- }
- default:
- err = fmt.Errorf("%w: invalid byte for exportdesc: %#x", ErrInvalidByte, b)
- }
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go
deleted file mode 100644
index bb9e2b649..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/function.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeFunctionType(enabledFeatures api.CoreFeatures, r *bytes.Reader, ret *wasm.FunctionType) (err error) {
- b, err := r.ReadByte()
- if err != nil {
- return fmt.Errorf("read leading byte: %w", err)
- }
-
- if b != 0x60 {
- return fmt.Errorf("%w: %#x != 0x60", ErrInvalidByte, b)
- }
-
- paramCount, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("could not read parameter count: %w", err)
- }
-
- paramTypes, err := decodeValueTypes(r, paramCount)
- if err != nil {
- return fmt.Errorf("could not read parameter types: %w", err)
- }
-
- resultCount, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return fmt.Errorf("could not read result count: %w", err)
- }
-
- // Guard >1.0 feature multi-value
- if resultCount > 1 {
- if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
- return fmt.Errorf("multiple result types invalid as %v", err)
- }
- }
-
- resultTypes, err := decodeValueTypes(r, resultCount)
- if err != nil {
- return fmt.Errorf("could not read result types: %w", err)
- }
-
- ret.Params = paramTypes
- ret.Results = resultTypes
-
- // cache the key for the function type
- _ = ret.String()
-
- return nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go
deleted file mode 100644
index 4e1c16fda..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/global.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-// decodeGlobal returns the api.Global decoded with the WebAssembly 1.0 (20191205) Binary Format.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-global
-func decodeGlobal(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.Global) (err error) {
- ret.Type, err = decodeGlobalType(r)
- if err != nil {
- return err
- }
-
- err = decodeConstantExpression(r, enabledFeatures, &ret.Init)
- return
-}
-
-// decodeGlobalType returns the wasm.GlobalType decoded with the WebAssembly 1.0 (20191205) Binary Format.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-globaltype
-func decodeGlobalType(r *bytes.Reader) (wasm.GlobalType, error) {
- vt, err := decodeValueTypes(r, 1)
- if err != nil {
- return wasm.GlobalType{}, fmt.Errorf("read value type: %w", err)
- }
-
- ret := wasm.GlobalType{
- ValType: vt[0],
- }
-
- b, err := r.ReadByte()
- if err != nil {
- return wasm.GlobalType{}, fmt.Errorf("read mutablity: %w", err)
- }
-
- switch mut := b; mut {
- case 0x00: // not mutable
- case 0x01: // mutable
- ret.Mutable = true
- default:
- return wasm.GlobalType{}, fmt.Errorf("%w for mutability: %#x != 0x00 or 0x01", ErrInvalidByte, mut)
- }
- return ret, nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go
deleted file mode 100644
index 29ba1b599..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/header.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package binary
-
-// Magic is the 4 byte preamble (literally "\0asm") of the binary format
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-magic
-var Magic = []byte{0x00, 0x61, 0x73, 0x6D}
-
-// version is format version and doesn't change between known specification versions
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-version
-var version = []byte{0x01, 0x00, 0x00, 0x00}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go
deleted file mode 100644
index 39d310c55..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/import.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeImport(
- r *bytes.Reader,
- idx uint32,
- memorySizer memorySizer,
- memoryLimitPages uint32,
- enabledFeatures api.CoreFeatures,
- ret *wasm.Import,
-) (err error) {
- if ret.Module, _, err = decodeUTF8(r, "import module"); err != nil {
- err = fmt.Errorf("import[%d] error decoding module: %w", idx, err)
- return
- }
-
- if ret.Name, _, err = decodeUTF8(r, "import name"); err != nil {
- err = fmt.Errorf("import[%d] error decoding name: %w", idx, err)
- return
- }
-
- b, err := r.ReadByte()
- if err != nil {
- err = fmt.Errorf("import[%d] error decoding type: %w", idx, err)
- return
- }
- ret.Type = b
- switch ret.Type {
- case wasm.ExternTypeFunc:
- ret.DescFunc, _, err = leb128.DecodeUint32(r)
- case wasm.ExternTypeTable:
- err = decodeTable(r, enabledFeatures, &ret.DescTable)
- case wasm.ExternTypeMemory:
- ret.DescMem, err = decodeMemory(r, enabledFeatures, memorySizer, memoryLimitPages)
- case wasm.ExternTypeGlobal:
- ret.DescGlobal, err = decodeGlobalType(r)
- default:
- err = fmt.Errorf("%w: invalid byte for importdesc: %#x", ErrInvalidByte, b)
- }
- if err != nil {
- err = fmt.Errorf("import[%d] %s[%s.%s]: %w", idx, wasm.ExternTypeName(ret.Type), ret.Module, ret.Name, err)
- }
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go
deleted file mode 100644
index ff2d73b5f..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/limits.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/internal/leb128"
-)
-
-// decodeLimitsType returns the `limitsType` (min, max) decoded with the WebAssembly 1.0 (20191205) Binary Format.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#limits%E2%91%A6
-//
-// Extended in threads proposal: https://webassembly.github.io/threads/core/binary/types.html#limits
-func decodeLimitsType(r *bytes.Reader) (min uint32, max *uint32, shared bool, err error) {
- var flag byte
- if flag, err = r.ReadByte(); err != nil {
- err = fmt.Errorf("read leading byte: %v", err)
- return
- }
-
- switch flag {
- case 0x00, 0x02:
- min, _, err = leb128.DecodeUint32(r)
- if err != nil {
- err = fmt.Errorf("read min of limit: %v", err)
- }
- case 0x01, 0x03:
- min, _, err = leb128.DecodeUint32(r)
- if err != nil {
- err = fmt.Errorf("read min of limit: %v", err)
- return
- }
- var m uint32
- if m, _, err = leb128.DecodeUint32(r); err != nil {
- err = fmt.Errorf("read max of limit: %v", err)
- } else {
- max = &m
- }
- default:
- err = fmt.Errorf("%v for limits: %#x not in (0x00, 0x01, 0x02, 0x03)", ErrInvalidByte, flag)
- }
-
- shared = flag == 0x02 || flag == 0x03
-
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go
deleted file mode 100644
index e1b175123..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/memory.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/experimental"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-// decodeMemory returns the api.Memory decoded with the WebAssembly 1.0 (20191205) Binary Format.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-memory
-func decodeMemory(
- r *bytes.Reader,
- enabledFeatures api.CoreFeatures,
- memorySizer func(minPages uint32, maxPages *uint32) (min, capacity, max uint32),
- memoryLimitPages uint32,
-) (*wasm.Memory, error) {
- min, maxP, shared, err := decodeLimitsType(r)
- if err != nil {
- return nil, err
- }
-
- if shared {
- if !enabledFeatures.IsEnabled(experimental.CoreFeaturesThreads) {
- return nil, fmt.Errorf("shared memory requested but threads feature not enabled")
- }
-
- // This restriction may be lifted in the future.
- // https://webassembly.github.io/threads/core/binary/types.html#memory-types
- if maxP == nil {
- return nil, fmt.Errorf("shared memory requires a maximum size to be specified")
- }
- }
-
- min, capacity, max := memorySizer(min, maxP)
- mem := &wasm.Memory{Min: min, Cap: capacity, Max: max, IsMaxEncoded: maxP != nil, IsShared: shared}
-
- return mem, mem.Validate(memoryLimitPages)
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go
deleted file mode 100644
index 56fb96dc8..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/names.go
+++ /dev/null
@@ -1,151 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
- "io"
-
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-const (
- // subsectionIDModuleName contains only the module name.
- subsectionIDModuleName = uint8(0)
- // subsectionIDFunctionNames is a map of indices to function names, in ascending order by function index
- subsectionIDFunctionNames = uint8(1)
- // subsectionIDLocalNames contain a map of function indices to a map of local indices to their names, in ascending
- // order by function and local index
- subsectionIDLocalNames = uint8(2)
-)
-
-// decodeNameSection deserializes the data associated with the "name" key in SectionIDCustom according to the
-// standard:
-//
-// * ModuleName decode from subsection 0
-// * FunctionNames decode from subsection 1
-// * LocalNames decode from subsection 2
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-namesec
-func decodeNameSection(r *bytes.Reader, limit uint64) (result *wasm.NameSection, err error) {
- // TODO: add leb128 functions that work on []byte and offset. While using a reader allows us to reuse reader-based
- // leb128 functions, it is less efficient, causes untestable code and in some cases more complex vs plain []byte.
- result = &wasm.NameSection{}
-
- // subsectionID is decoded if known, and skipped if not
- var subsectionID uint8
- // subsectionSize is the length to skip when the subsectionID is unknown
- var subsectionSize uint32
- var bytesRead uint64
- for limit > 0 {
- if subsectionID, err = r.ReadByte(); err != nil {
- if err == io.EOF {
- return result, nil
- }
- // TODO: untestable as this can't fail for a reason beside EOF reading a byte from a buffer
- return nil, fmt.Errorf("failed to read a subsection ID: %w", err)
- }
- limit--
-
- if subsectionSize, bytesRead, err = leb128.DecodeUint32(r); err != nil {
- return nil, fmt.Errorf("failed to read the size of subsection[%d]: %w", subsectionID, err)
- }
- limit -= bytesRead
-
- switch subsectionID {
- case subsectionIDModuleName:
- if result.ModuleName, _, err = decodeUTF8(r, "module name"); err != nil {
- return nil, err
- }
- case subsectionIDFunctionNames:
- if result.FunctionNames, err = decodeFunctionNames(r); err != nil {
- return nil, err
- }
- case subsectionIDLocalNames:
- if result.LocalNames, err = decodeLocalNames(r); err != nil {
- return nil, err
- }
- default: // Skip other subsections.
- // Note: Not Seek because it doesn't err when given an offset past EOF. Rather, it leads to undefined state.
- if _, err = io.CopyN(io.Discard, r, int64(subsectionSize)); err != nil {
- return nil, fmt.Errorf("failed to skip subsection[%d]: %w", subsectionID, err)
- }
- }
- limit -= uint64(subsectionSize)
- }
- return
-}
-
-func decodeFunctionNames(r *bytes.Reader) (wasm.NameMap, error) {
- functionCount, err := decodeFunctionCount(r, subsectionIDFunctionNames)
- if err != nil {
- return nil, err
- }
-
- result := make(wasm.NameMap, functionCount)
- for i := uint32(0); i < functionCount; i++ {
- functionIndex, err := decodeFunctionIndex(r, subsectionIDFunctionNames)
- if err != nil {
- return nil, err
- }
-
- name, _, err := decodeUTF8(r, "function[%d] name", functionIndex)
- if err != nil {
- return nil, err
- }
- result[i] = wasm.NameAssoc{Index: functionIndex, Name: name}
- }
- return result, nil
-}
-
-func decodeLocalNames(r *bytes.Reader) (wasm.IndirectNameMap, error) {
- functionCount, err := decodeFunctionCount(r, subsectionIDLocalNames)
- if err != nil {
- return nil, err
- }
-
- result := make(wasm.IndirectNameMap, functionCount)
- for i := uint32(0); i < functionCount; i++ {
- functionIndex, err := decodeFunctionIndex(r, subsectionIDLocalNames)
- if err != nil {
- return nil, err
- }
-
- localCount, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("failed to read the local count for function[%d]: %w", functionIndex, err)
- }
-
- locals := make(wasm.NameMap, localCount)
- for j := uint32(0); j < localCount; j++ {
- localIndex, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("failed to read a local index of function[%d]: %w", functionIndex, err)
- }
-
- name, _, err := decodeUTF8(r, "function[%d] local[%d] name", functionIndex, localIndex)
- if err != nil {
- return nil, err
- }
- locals[j] = wasm.NameAssoc{Index: localIndex, Name: name}
- }
- result[i] = wasm.NameMapAssoc{Index: functionIndex, NameMap: locals}
- }
- return result, nil
-}
-
-func decodeFunctionIndex(r *bytes.Reader, subsectionID uint8) (uint32, error) {
- functionIndex, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return 0, fmt.Errorf("failed to read a function index in subsection[%d]: %w", subsectionID, err)
- }
- return functionIndex, nil
-}
-
-func decodeFunctionCount(r *bytes.Reader, subsectionID uint8) (uint32, error) {
- functionCount, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return 0, fmt.Errorf("failed to read the function count of subsection[%d]: %w", subsectionID, err)
- }
- return functionCount, nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go
deleted file mode 100644
index 622ee5923..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/section.go
+++ /dev/null
@@ -1,226 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
- "io"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeTypeSection(enabledFeatures api.CoreFeatures, r *bytes.Reader) ([]wasm.FunctionType, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- result := make([]wasm.FunctionType, vs)
- for i := uint32(0); i < vs; i++ {
- if err = decodeFunctionType(enabledFeatures, r, &result[i]); err != nil {
- return nil, fmt.Errorf("read %d-th type: %v", i, err)
- }
- }
- return result, nil
-}
-
-// decodeImportSection decodes the decoded import segments plus the count per wasm.ExternType.
-func decodeImportSection(
- r *bytes.Reader,
- memorySizer memorySizer,
- memoryLimitPages uint32,
- enabledFeatures api.CoreFeatures,
-) (result []wasm.Import,
- perModule map[string][]*wasm.Import,
- funcCount, globalCount, memoryCount, tableCount wasm.Index, err error,
-) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- err = fmt.Errorf("get size of vector: %w", err)
- return
- }
-
- perModule = make(map[string][]*wasm.Import)
- result = make([]wasm.Import, vs)
- for i := uint32(0); i < vs; i++ {
- imp := &result[i]
- if err = decodeImport(r, i, memorySizer, memoryLimitPages, enabledFeatures, imp); err != nil {
- return
- }
- switch imp.Type {
- case wasm.ExternTypeFunc:
- imp.IndexPerType = funcCount
- funcCount++
- case wasm.ExternTypeGlobal:
- imp.IndexPerType = globalCount
- globalCount++
- case wasm.ExternTypeMemory:
- imp.IndexPerType = memoryCount
- memoryCount++
- case wasm.ExternTypeTable:
- imp.IndexPerType = tableCount
- tableCount++
- }
- perModule[imp.Module] = append(perModule[imp.Module], imp)
- }
- return
-}
-
-func decodeFunctionSection(r *bytes.Reader) ([]uint32, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- result := make([]uint32, vs)
- for i := uint32(0); i < vs; i++ {
- if result[i], _, err = leb128.DecodeUint32(r); err != nil {
- return nil, fmt.Errorf("get type index: %w", err)
- }
- }
- return result, err
-}
-
-func decodeTableSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Table, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("error reading size")
- }
- if vs > 1 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return nil, fmt.Errorf("at most one table allowed in module as %w", err)
- }
- }
-
- ret := make([]wasm.Table, vs)
- for i := range ret {
- err = decodeTable(r, enabledFeatures, &ret[i])
- if err != nil {
- return nil, err
- }
- }
- return ret, nil
-}
-
-func decodeMemorySection(
- r *bytes.Reader,
- enabledFeatures api.CoreFeatures,
- memorySizer memorySizer,
- memoryLimitPages uint32,
-) (*wasm.Memory, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("error reading size")
- }
- if vs > 1 {
- return nil, fmt.Errorf("at most one memory allowed in module, but read %d", vs)
- } else if vs == 0 {
- // memory count can be zero.
- return nil, nil
- }
-
- return decodeMemory(r, enabledFeatures, memorySizer, memoryLimitPages)
-}
-
-func decodeGlobalSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.Global, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- result := make([]wasm.Global, vs)
- for i := uint32(0); i < vs; i++ {
- if err = decodeGlobal(r, enabledFeatures, &result[i]); err != nil {
- return nil, fmt.Errorf("global[%d]: %w", i, err)
- }
- }
- return result, nil
-}
-
-func decodeExportSection(r *bytes.Reader) ([]wasm.Export, map[string]*wasm.Export, error) {
- vs, _, sizeErr := leb128.DecodeUint32(r)
- if sizeErr != nil {
- return nil, nil, fmt.Errorf("get size of vector: %v", sizeErr)
- }
-
- exportMap := make(map[string]*wasm.Export, vs)
- exportSection := make([]wasm.Export, vs)
- for i := wasm.Index(0); i < vs; i++ {
- export := &exportSection[i]
- err := decodeExport(r, export)
- if err != nil {
- return nil, nil, fmt.Errorf("read export: %w", err)
- }
- if _, ok := exportMap[export.Name]; ok {
- return nil, nil, fmt.Errorf("export[%d] duplicates name %q", i, export.Name)
- } else {
- exportMap[export.Name] = export
- }
- }
- return exportSection, exportMap, nil
-}
-
-func decodeStartSection(r *bytes.Reader) (*wasm.Index, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get function index: %w", err)
- }
- return &vs, nil
-}
-
-func decodeElementSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.ElementSegment, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- result := make([]wasm.ElementSegment, vs)
- for i := uint32(0); i < vs; i++ {
- if err = decodeElementSegment(r, enabledFeatures, &result[i]); err != nil {
- return nil, fmt.Errorf("read element: %w", err)
- }
- }
- return result, nil
-}
-
-func decodeCodeSection(r *bytes.Reader) ([]wasm.Code, error) {
- codeSectionStart := uint64(r.Len())
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- result := make([]wasm.Code, vs)
- for i := uint32(0); i < vs; i++ {
- err = decodeCode(r, codeSectionStart, &result[i])
- if err != nil {
- return nil, fmt.Errorf("read %d-th code segment: %v", i, err)
- }
- }
- return result, nil
-}
-
-func decodeDataSection(r *bytes.Reader, enabledFeatures api.CoreFeatures) ([]wasm.DataSegment, error) {
- vs, _, err := leb128.DecodeUint32(r)
- if err != nil {
- return nil, fmt.Errorf("get size of vector: %w", err)
- }
-
- result := make([]wasm.DataSegment, vs)
- for i := uint32(0); i < vs; i++ {
- if err = decodeDataSegment(r, enabledFeatures, &result[i]); err != nil {
- return nil, fmt.Errorf("read data segment: %w", err)
- }
- }
- return result, nil
-}
-
-func decodeDataCountSection(r *bytes.Reader) (count *uint32, err error) {
- v, _, err := leb128.DecodeUint32(r)
- if err != nil && err != io.EOF {
- // data count is optional, so EOF is fine.
- return nil, err
- }
- return &v, nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go
deleted file mode 100644
index 353ec7566..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/table.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-// decodeTable returns the wasm.Table decoded with the WebAssembly 1.0 (20191205) Binary Format.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-table
-func decodeTable(r *bytes.Reader, enabledFeatures api.CoreFeatures, ret *wasm.Table) (err error) {
- ret.Type, err = r.ReadByte()
- if err != nil {
- return fmt.Errorf("read leading byte: %v", err)
- }
-
- if ret.Type != wasm.RefTypeFuncref {
- if err = enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("table type funcref is invalid: %w", err)
- }
- }
-
- var shared bool
- ret.Min, ret.Max, shared, err = decodeLimitsType(r)
- if err != nil {
- return fmt.Errorf("read limits: %v", err)
- }
- if ret.Min > wasm.MaximumFunctionIndex {
- return fmt.Errorf("table min must be at most %d", wasm.MaximumFunctionIndex)
- }
- if ret.Max != nil {
- if *ret.Max < ret.Min {
- return fmt.Errorf("table size minimum must not be greater than maximum")
- }
- }
- if shared {
- return fmt.Errorf("tables cannot be marked as shared")
- }
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go
deleted file mode 100644
index dfc4417ed..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/binary/value.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package binary
-
-import (
- "bytes"
- "fmt"
- "io"
- "unicode/utf8"
- "unsafe"
-
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasm"
-)
-
-func decodeValueTypes(r *bytes.Reader, num uint32) ([]wasm.ValueType, error) {
- if num == 0 {
- return nil, nil
- }
-
- ret := make([]wasm.ValueType, num)
- _, err := io.ReadFull(r, ret)
- if err != nil {
- return nil, err
- }
-
- for _, v := range ret {
- switch v {
- case wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeI64, wasm.ValueTypeF64,
- wasm.ValueTypeExternref, wasm.ValueTypeFuncref, wasm.ValueTypeV128:
- default:
- return nil, fmt.Errorf("invalid value type: %d", v)
- }
- }
- return ret, nil
-}
-
-// decodeUTF8 decodes a size prefixed string from the reader, returning it and the count of bytes read.
-// contextFormat and contextArgs apply an error format when present
-func decodeUTF8(r *bytes.Reader, contextFormat string, contextArgs ...interface{}) (string, uint32, error) {
- size, sizeOfSize, err := leb128.DecodeUint32(r)
- if err != nil {
- return "", 0, fmt.Errorf("failed to read %s size: %w", fmt.Sprintf(contextFormat, contextArgs...), err)
- }
-
- if size == 0 {
- return "", uint32(sizeOfSize), nil
- }
-
- buf := make([]byte, size)
- if _, err = io.ReadFull(r, buf); err != nil {
- return "", 0, fmt.Errorf("failed to read %s: %w", fmt.Sprintf(contextFormat, contextArgs...), err)
- }
-
- if !utf8.Valid(buf) {
- return "", 0, fmt.Errorf("%s is not valid UTF-8", fmt.Sprintf(contextFormat, contextArgs...))
- }
-
- ret := unsafe.String(&buf[0], int(size))
- return ret, size + uint32(sizeOfSize), nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go
deleted file mode 100644
index 685a40941..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/counts.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package wasm
-
-import "fmt"
-
-// SectionElementCount returns the count of elements in a given section ID
-//
-// For example...
-// * SectionIDType returns the count of FunctionType
-// * SectionIDCustom returns the count of CustomSections plus one if NameSection is present
-// * SectionIDHostFunction returns the count of HostFunctionSection
-// * SectionIDExport returns the count of unique export names
-func (m *Module) SectionElementCount(sectionID SectionID) uint32 { // element as in vector elements!
- switch sectionID {
- case SectionIDCustom:
- numCustomSections := uint32(len(m.CustomSections))
- if m.NameSection != nil {
- numCustomSections++
- }
- return numCustomSections
- case SectionIDType:
- return uint32(len(m.TypeSection))
- case SectionIDImport:
- return uint32(len(m.ImportSection))
- case SectionIDFunction:
- return uint32(len(m.FunctionSection))
- case SectionIDTable:
- return uint32(len(m.TableSection))
- case SectionIDMemory:
- if m.MemorySection != nil {
- return 1
- }
- return 0
- case SectionIDGlobal:
- return uint32(len(m.GlobalSection))
- case SectionIDExport:
- return uint32(len(m.ExportSection))
- case SectionIDStart:
- if m.StartSection != nil {
- return 1
- }
- return 0
- case SectionIDElement:
- return uint32(len(m.ElementSection))
- case SectionIDCode:
- return uint32(len(m.CodeSection))
- case SectionIDData:
- return uint32(len(m.DataSection))
- default:
- panic(fmt.Errorf("BUG: unknown section: %d", sectionID))
- }
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go
deleted file mode 100644
index 8c387e9e1..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/engine.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package wasm
-
-import (
- "context"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/experimental"
-)
-
-// Engine is a Store-scoped mechanism to compile functions declared or imported by a module.
-// This is a top-level type implemented by an interpreter or compiler.
-type Engine interface {
- // Close closes this engine, and releases all the compiled cache.
- Close() (err error)
-
- // CompileModule implements the same method as documented on wasm.Engine.
- CompileModule(ctx context.Context, module *Module, listeners []experimental.FunctionListener, ensureTermination bool) error
-
- // CompiledModuleCount is exported for testing, to track the size of the compilation cache.
- CompiledModuleCount() uint32
-
- // DeleteCompiledModule releases compilation caches for the given module (source).
- // Note: it is safe to call this function for a module from which module instances are instantiated even when these
- // module instances have outstanding calls.
- DeleteCompiledModule(module *Module)
-
- // NewModuleEngine compiles down the function instances in a module, and returns ModuleEngine for the module.
- //
- // * module is the source module from which moduleFunctions are instantiated. This is used for caching.
- // * instance is the *ModuleInstance which is created from `module`.
- //
- // Note: Input parameters must be pre-validated with wasm.Module Validate, to ensure no fields are invalid
- // due to reasons such as out-of-bounds.
- NewModuleEngine(module *Module, instance *ModuleInstance) (ModuleEngine, error)
-}
-
-// ModuleEngine implements function calls for a given module.
-type ModuleEngine interface {
- // DoneInstantiation is called at the end of the instantiation of the module.
- DoneInstantiation()
-
- // NewFunction returns an api.Function for the given function pointed by the given Index.
- NewFunction(index Index) api.Function
-
- // ResolveImportedFunction is used to add imported functions needed to make this ModuleEngine fully functional.
- // - `index` is the function Index of this imported function.
- // - `descFunc` is the type Index in Module.TypeSection of this imported function. It corresponds to Import.DescFunc.
- // - `indexInImportedModule` is the function Index of the imported function in the imported module.
- // - `importedModuleEngine` is the ModuleEngine for the imported ModuleInstance.
- ResolveImportedFunction(index, descFunc, indexInImportedModule Index, importedModuleEngine ModuleEngine)
-
- // ResolveImportedMemory is called when this module imports a memory from another module.
- ResolveImportedMemory(importedModuleEngine ModuleEngine)
-
- // LookupFunction returns the FunctionModule and the Index of the function in the returned ModuleInstance at the given offset in the table.
- LookupFunction(t *TableInstance, typeId FunctionTypeID, tableOffset Index) (*ModuleInstance, Index)
-
- // GetGlobalValue returns the value of the global variable at the given Index.
- // Only called when OwnsGlobals() returns true, and must not be called for imported globals
- GetGlobalValue(idx Index) (lo, hi uint64)
-
- // SetGlobalValue sets the value of the global variable at the given Index.
- // Only called when OwnsGlobals() returns true, and must not be called for imported globals
- SetGlobalValue(idx Index, lo, hi uint64)
-
- // OwnsGlobals returns true if this ModuleEngine owns the global variables. If true, wasm.GlobalInstance's Val,ValHi should
- // not be accessed directly.
- OwnsGlobals() bool
-
- // FunctionInstanceReference returns Reference for the given Index for a FunctionInstance. The returned values are used by
- // the initialization via ElementSegment.
- FunctionInstanceReference(funcIndex Index) Reference
-
- // MemoryGrown notifies the engine that the memory has grown.
- MemoryGrown()
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go
deleted file mode 100644
index 604489228..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/func_validation.go
+++ /dev/null
@@ -1,2336 +0,0 @@
-package wasm
-
-import (
- "bytes"
- "errors"
- "fmt"
- "strconv"
- "strings"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/experimental"
- "github.com/tetratelabs/wazero/internal/leb128"
-)
-
-// The wazero specific limitation described at RATIONALE.md.
-const maximumValuesOnStack = 1 << 27
-
-// validateFunction validates the instruction sequence of a function.
-// following the specification https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#instructions%E2%91%A2.
-//
-// * idx is the index in the FunctionSection
-// * functions are the function index, which is prefixed by imports. The value is the TypeSection index.
-// * globals are the global index, which is prefixed by imports.
-// * memory is the potentially imported memory and can be nil.
-// * table is the potentially imported table and can be nil.
-// * declaredFunctionIndexes is the set of function indexes declared by declarative element segments which can be acceed by OpcodeRefFunc instruction.
-//
-// Returns an error if the instruction sequence is not valid,
-// or potentially it can exceed the maximum number of values on the stack.
-func (m *Module) validateFunction(sts *stacks, enabledFeatures api.CoreFeatures, idx Index, functions []Index,
- globals []GlobalType, memory *Memory, tables []Table, declaredFunctionIndexes map[Index]struct{}, br *bytes.Reader,
-) error {
- return m.validateFunctionWithMaxStackValues(sts, enabledFeatures, idx, functions, globals, memory, tables, maximumValuesOnStack, declaredFunctionIndexes, br)
-}
-
-func readMemArg(pc uint64, body []byte) (align, offset uint32, read uint64, err error) {
- align, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- err = fmt.Errorf("read memory align: %v", err)
- return
- }
- read += num
-
- offset, num, err = leb128.LoadUint32(body[pc+num:])
- if err != nil {
- err = fmt.Errorf("read memory offset: %v", err)
- return
- }
-
- read += num
- return align, offset, read, nil
-}
-
-// validateFunctionWithMaxStackValues is like validateFunction, but allows overriding maxStackValues for testing.
-//
-// * stacks is to track the state of Wasm value and control frame stacks at anypoint of execution, and reused to reduce allocation.
-// * maxStackValues is the maximum height of values stack which the target is allowed to reach.
-func (m *Module) validateFunctionWithMaxStackValues(
- sts *stacks,
- enabledFeatures api.CoreFeatures,
- idx Index,
- functions []Index,
- globals []GlobalType,
- memory *Memory,
- tables []Table,
- maxStackValues int,
- declaredFunctionIndexes map[Index]struct{},
- br *bytes.Reader,
-) error {
- functionType := &m.TypeSection[m.FunctionSection[idx]]
- code := &m.CodeSection[idx]
- body := code.Body
- localTypes := code.LocalTypes
-
- sts.reset(functionType)
- valueTypeStack := &sts.vs
- // We start with the outermost control block which is for function return if the code branches into it.
- controlBlockStack := &sts.cs
-
- // Now start walking through all the instructions in the body while tracking
- // control blocks and value types to check the validity of all instructions.
- for pc := uint64(0); pc < uint64(len(body)); pc++ {
- op := body[pc]
- if false {
- var instName string
- if op == OpcodeMiscPrefix {
- instName = MiscInstructionName(body[pc+1])
- } else if op == OpcodeVecPrefix {
- instName = VectorInstructionName(body[pc+1])
- } else if op == OpcodeAtomicPrefix {
- instName = AtomicInstructionName(body[pc+1])
- } else {
- instName = InstructionName(op)
- }
- fmt.Printf("handling %s, stack=%s, blocks: %v\n", instName, valueTypeStack.stack, controlBlockStack)
- }
-
- if len(controlBlockStack.stack) == 0 {
- return fmt.Errorf("unexpected end of function at pc=%#x", pc)
- }
-
- if OpcodeI32Load <= op && op <= OpcodeI64Store32 {
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", InstructionName(op))
- }
- pc++
- align, _, read, err := readMemArg(pc, body)
- if err != nil {
- return err
- }
- pc += read - 1
- switch op {
- case OpcodeI32Load:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeF32Load:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeI32Store:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeF32Store:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeI64Load:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeF64Load:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeI64Store:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeF64Store:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeI32Load8S:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI32Load8U:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Load8S, OpcodeI64Load8U:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeI32Store8:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeI64Store8:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeI32Load16S, OpcodeI32Load16U:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Load16S, OpcodeI64Load16U:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeI32Store16:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeI64Store16:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeI64Load32S, OpcodeI64Load32U:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeI64Store32:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- }
- } else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow {
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", InstructionName(op))
- }
- pc++
- val, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- }
- if val != 0 || num != 1 {
- return fmt.Errorf("memory instruction reserved bytes not zero with 1 byte")
- }
- switch Opcode(op) {
- case OpcodeMemoryGrow:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeMemorySize:
- valueTypeStack.push(ValueTypeI32)
- }
- pc += num - 1
- } else if OpcodeI32Const <= op && op <= OpcodeF64Const {
- pc++
- switch Opcode(op) {
- case OpcodeI32Const:
- _, num, err := leb128.LoadInt32(body[pc:])
- if err != nil {
- return fmt.Errorf("read i32 immediate: %s", err)
- }
- pc += num - 1
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Const:
- _, num, err := leb128.LoadInt64(body[pc:])
- if err != nil {
- return fmt.Errorf("read i64 immediate: %v", err)
- }
- valueTypeStack.push(ValueTypeI64)
- pc += num - 1
- case OpcodeF32Const:
- valueTypeStack.push(ValueTypeF32)
- pc += 3
- case OpcodeF64Const:
- valueTypeStack.push(ValueTypeF64)
- pc += 7
- }
- } else if OpcodeLocalGet <= op && op <= OpcodeGlobalSet {
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- }
- pc += num - 1
- switch op {
- case OpcodeLocalGet:
- inputLen := uint32(len(functionType.Params))
- if l := uint32(len(localTypes)) + inputLen; index >= l {
- return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
- OpcodeLocalGetName, index, l)
- }
- if index < inputLen {
- valueTypeStack.push(functionType.Params[index])
- } else {
- valueTypeStack.push(localTypes[index-inputLen])
- }
- case OpcodeLocalSet:
- inputLen := uint32(len(functionType.Params))
- if l := uint32(len(localTypes)) + inputLen; index >= l {
- return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
- OpcodeLocalSetName, index, l)
- }
- var expType ValueType
- if index < inputLen {
- expType = functionType.Params[index]
- } else {
- expType = localTypes[index-inputLen]
- }
- if err := valueTypeStack.popAndVerifyType(expType); err != nil {
- return err
- }
- case OpcodeLocalTee:
- inputLen := uint32(len(functionType.Params))
- if l := uint32(len(localTypes)) + inputLen; index >= l {
- return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
- OpcodeLocalTeeName, index, l)
- }
- var expType ValueType
- if index < inputLen {
- expType = functionType.Params[index]
- } else {
- expType = localTypes[index-inputLen]
- }
- if err := valueTypeStack.popAndVerifyType(expType); err != nil {
- return err
- }
- valueTypeStack.push(expType)
- case OpcodeGlobalGet:
- if index >= uint32(len(globals)) {
- return fmt.Errorf("invalid index for %s", OpcodeGlobalGetName)
- }
- valueTypeStack.push(globals[index].ValType)
- case OpcodeGlobalSet:
- if index >= uint32(len(globals)) {
- return fmt.Errorf("invalid global index")
- } else if !globals[index].Mutable {
- return fmt.Errorf("%s when not mutable", OpcodeGlobalSetName)
- } else if err := valueTypeStack.popAndVerifyType(
- globals[index].ValType); err != nil {
- return err
- }
- }
- } else if op == OpcodeBr {
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- } else if int(index) >= len(controlBlockStack.stack) {
- return fmt.Errorf("invalid %s operation: index out of range", OpcodeBrName)
- }
- pc += num - 1
- // Check type soundness.
- target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
- var targetResultType []ValueType
- if target.op == OpcodeLoop {
- targetResultType = target.blockType.Params
- } else {
- targetResultType = target.blockType.Results
- }
- if err = valueTypeStack.popResults(op, targetResultType, false); err != nil {
- return err
- }
- // br instruction is stack-polymorphic.
- valueTypeStack.unreachable()
- } else if op == OpcodeBrIf {
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- } else if int(index) >= len(controlBlockStack.stack) {
- return fmt.Errorf(
- "invalid ln param given for %s: index=%d with %d for the current label stack length",
- OpcodeBrIfName, index, len(controlBlockStack.stack))
- }
- pc += num - 1
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrIfName)
- }
- // Check type soundness.
- target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
- var targetResultType []ValueType
- if target.op == OpcodeLoop {
- targetResultType = target.blockType.Params
- } else {
- targetResultType = target.blockType.Results
- }
- if err := valueTypeStack.popResults(op, targetResultType, false); err != nil {
- return err
- }
- // Push back the result
- for _, t := range targetResultType {
- valueTypeStack.push(t)
- }
- } else if op == OpcodeBrTable {
- pc++
- br.Reset(body[pc:])
- nl, num, err := leb128.DecodeUint32(br)
- if err != nil {
- return fmt.Errorf("read immediate: %w", err)
- }
-
- sts.ls = sts.ls[:0]
- for i := uint32(0); i < nl; i++ {
- l, n, err := leb128.DecodeUint32(br)
- if err != nil {
- return fmt.Errorf("read immediate: %w", err)
- }
- num += n
- sts.ls = append(sts.ls, l)
- }
- ln, n, err := leb128.DecodeUint32(br)
- if err != nil {
- return fmt.Errorf("read immediate: %w", err)
- } else if int(ln) >= len(controlBlockStack.stack) {
- return fmt.Errorf(
- "invalid ln param given for %s: ln=%d with %d for the current label stack length",
- OpcodeBrTableName, ln, len(controlBlockStack.stack))
- }
- pc += n + num - 1
- // Check type soundness.
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrTableName)
- }
- lnLabel := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(ln)]
- var defaultLabelType []ValueType
- // Below, we might modify the slice in case of unreachable. Therefore,
- // we have to copy the content of block result types, otherwise the original
- // function type might result in invalid value types if the block is the outermost label
- // which equals the function's type.
- if lnLabel.op != OpcodeLoop { // Loop operation doesn't require results since the continuation is the beginning of the loop.
- defaultLabelType = make([]ValueType, len(lnLabel.blockType.Results))
- copy(defaultLabelType, lnLabel.blockType.Results)
- } else {
- defaultLabelType = make([]ValueType, len(lnLabel.blockType.Params))
- copy(defaultLabelType, lnLabel.blockType.Params)
- }
-
- if enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) {
- // As of reference-types proposal, br_table on unreachable state
- // can choose unknown types for expected parameter types for each label.
- // https://github.com/WebAssembly/reference-types/pull/116
- for i := range defaultLabelType {
- index := len(defaultLabelType) - 1 - i
- exp := defaultLabelType[index]
- actual, err := valueTypeStack.pop()
- if err != nil {
- return err
- }
- if actual == valueTypeUnknown {
- // Re-assign the expected type to unknown.
- defaultLabelType[index] = valueTypeUnknown
- } else if actual != exp {
- return typeMismatchError(true, OpcodeBrTableName, actual, exp, i)
- }
- }
- } else {
- if err = valueTypeStack.popResults(op, defaultLabelType, false); err != nil {
- return err
- }
- }
-
- for _, l := range sts.ls {
- if int(l) >= len(controlBlockStack.stack) {
- return fmt.Errorf("invalid l param given for %s", OpcodeBrTableName)
- }
- label := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(l)]
- var tableLabelType []ValueType
- if label.op != OpcodeLoop {
- tableLabelType = label.blockType.Results
- } else {
- tableLabelType = label.blockType.Params
- }
- if len(defaultLabelType) != len(tableLabelType) {
- return fmt.Errorf("inconsistent block type length for %s at %d; %v (ln=%d) != %v (l=%d)", OpcodeBrTableName, l, defaultLabelType, ln, tableLabelType, l)
- }
- for i := range defaultLabelType {
- if defaultLabelType[i] != valueTypeUnknown && defaultLabelType[i] != tableLabelType[i] {
- return fmt.Errorf("incosistent block type for %s at %d", OpcodeBrTableName, l)
- }
- }
- }
-
- // br_table instruction is stack-polymorphic.
- valueTypeStack.unreachable()
- } else if op == OpcodeCall {
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- }
- pc += num - 1
- if int(index) >= len(functions) {
- return fmt.Errorf("invalid function index")
- }
- funcType := &m.TypeSection[functions[index]]
- for i := 0; i < len(funcType.Params); i++ {
- if err := valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
- return fmt.Errorf("type mismatch on %s operation param type: %v", OpcodeCallName, err)
- }
- }
- for _, exp := range funcType.Results {
- valueTypeStack.push(exp)
- }
- } else if op == OpcodeCallIndirect {
- pc++
- typeIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- }
- pc += num
-
- if int(typeIndex) >= len(m.TypeSection) {
- return fmt.Errorf("invalid type index at %s: %d", OpcodeCallIndirectName, typeIndex)
- }
-
- tableIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read table index: %v", err)
- }
- pc += num - 1
- if tableIndex != 0 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("table index must be zero but was %d: %w", tableIndex, err)
- }
- }
-
- if tableIndex >= uint32(len(tables)) {
- return fmt.Errorf("unknown table index: %d", tableIndex)
- }
-
- table := tables[tableIndex]
- if table.Type != RefTypeFuncref {
- return fmt.Errorf("table is not funcref type but was %s for %s", RefTypeName(table.Type), OpcodeCallIndirectName)
- }
-
- if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the offset in table for %s", OpcodeCallIndirectName)
- }
- funcType := &m.TypeSection[typeIndex]
- for i := 0; i < len(funcType.Params); i++ {
- if err = valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
- return fmt.Errorf("type mismatch on %s operation input type", OpcodeCallIndirectName)
- }
- }
- for _, exp := range funcType.Results {
- valueTypeStack.push(exp)
- }
- } else if OpcodeI32Eqz <= op && op <= OpcodeI64Extend32S {
- switch op {
- case OpcodeI32Eqz:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32EqzName, err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI32Eq, OpcodeI32Ne, OpcodeI32LtS,
- OpcodeI32LtU, OpcodeI32GtS, OpcodeI32GtU, OpcodeI32LeS,
- OpcodeI32LeU, OpcodeI32GeS, OpcodeI32GeU:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the 1st i32 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the 2nd i32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Eqz:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64EqzName, err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Eq, OpcodeI64Ne, OpcodeI64LtS,
- OpcodeI64LtU, OpcodeI64GtS, OpcodeI64GtU,
- OpcodeI64LeS, OpcodeI64LeU, OpcodeI64GeS, OpcodeI64GeU:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeF32Eq, OpcodeF32Ne, OpcodeF32Lt, OpcodeF32Gt, OpcodeF32Le, OpcodeF32Ge:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeF64Eq, OpcodeF64Ne, OpcodeF64Lt, OpcodeF64Gt, OpcodeF64Le, OpcodeF64Ge:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI32Clz, OpcodeI32Ctz, OpcodeI32Popcnt:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI32Add, OpcodeI32Sub, OpcodeI32Mul, OpcodeI32DivS,
- OpcodeI32DivU, OpcodeI32RemS, OpcodeI32RemU, OpcodeI32And,
- OpcodeI32Or, OpcodeI32Xor, OpcodeI32Shl, OpcodeI32ShrS,
- OpcodeI32ShrU, OpcodeI32Rotl, OpcodeI32Rotr:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the 1st operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the 2nd operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Clz, OpcodeI64Ctz, OpcodeI64Popcnt:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeI64Add, OpcodeI64Sub, OpcodeI64Mul, OpcodeI64DivS,
- OpcodeI64DivU, OpcodeI64RemS, OpcodeI64RemU, OpcodeI64And,
- OpcodeI64Or, OpcodeI64Xor, OpcodeI64Shl, OpcodeI64ShrS,
- OpcodeI64ShrU, OpcodeI64Rotl, OpcodeI64Rotr:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeF32Abs, OpcodeF32Neg, OpcodeF32Ceil,
- OpcodeF32Floor, OpcodeF32Trunc, OpcodeF32Nearest,
- OpcodeF32Sqrt:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeF32Add, OpcodeF32Sub, OpcodeF32Mul,
- OpcodeF32Div, OpcodeF32Min, OpcodeF32Max,
- OpcodeF32Copysign:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeF64Abs, OpcodeF64Neg, OpcodeF64Ceil,
- OpcodeF64Floor, OpcodeF64Trunc, OpcodeF64Nearest,
- OpcodeF64Sqrt:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeF64Add, OpcodeF64Sub, OpcodeF64Mul,
- OpcodeF64Div, OpcodeF64Min, OpcodeF64Max,
- OpcodeF64Copysign:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeI32WrapI64:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32WrapI64Name, err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI32TruncF32S, OpcodeI32TruncF32U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI32TruncF64S, OpcodeI32TruncF64U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64ExtendI32S, OpcodeI64ExtendI32U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeI64TruncF32S, OpcodeI64TruncF32U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeI64TruncF64S, OpcodeI64TruncF64U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeF32ConvertI32S, OpcodeF32ConvertI32U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeF32ConvertI64S, OpcodeF32ConvertI64U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeF32DemoteF64:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32DemoteF64Name, err)
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeF64ConvertI32S, OpcodeF64ConvertI32U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeF64ConvertI64S, OpcodeF64ConvertI64U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeF64PromoteF32:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64PromoteF32Name, err)
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeI32ReinterpretF32:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32ReinterpretF32Name, err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64ReinterpretF64:
- if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64ReinterpretF64Name, err)
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeF32ReinterpretI32:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32ReinterpretI32Name, err)
- }
- valueTypeStack.push(ValueTypeF32)
- case OpcodeF64ReinterpretI64:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64ReinterpretI64Name, err)
- }
- valueTypeStack.push(ValueTypeF64)
- case OpcodeI32Extend8S, OpcodeI32Extend16S:
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
- return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeI64Extend8S, OpcodeI64Extend16S, OpcodeI64Extend32S:
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
- return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
- }
- valueTypeStack.push(ValueTypeI64)
- default:
- return fmt.Errorf("invalid numeric instruction 0x%x", op)
- }
- } else if op >= OpcodeRefNull && op <= OpcodeRefFunc {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
- }
- switch op {
- case OpcodeRefNull:
- pc++
- switch reftype := body[pc]; reftype {
- case ValueTypeExternref:
- valueTypeStack.push(ValueTypeExternref)
- case ValueTypeFuncref:
- valueTypeStack.push(ValueTypeFuncref)
- default:
- return fmt.Errorf("unknown type for ref.null: 0x%x", reftype)
- }
- case OpcodeRefIsNull:
- tp, err := valueTypeStack.pop()
- if err != nil {
- return fmt.Errorf("cannot pop the operand for ref.is_null: %v", err)
- } else if !isReferenceValueType(tp) && tp != valueTypeUnknown {
- return fmt.Errorf("type mismatch: expected reference type but was %s", ValueTypeName(tp))
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeRefFunc:
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read function index for ref.func: %v", err)
- }
- if _, ok := declaredFunctionIndexes[index]; !ok {
- return fmt.Errorf("undeclared function index %d for ref.func", index)
- }
- pc += num - 1
- valueTypeStack.push(ValueTypeFuncref)
- }
- } else if op == OpcodeTableGet || op == OpcodeTableSet {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("%s is invalid as %v", InstructionName(op), err)
- }
- pc++
- tableIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("read immediate: %v", err)
- }
- if tableIndex >= uint32(len(tables)) {
- return fmt.Errorf("table of index %d not found", tableIndex)
- }
-
- refType := tables[tableIndex].Type
- if op == OpcodeTableGet {
- if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for table.get: %v", err)
- }
- valueTypeStack.push(refType)
- } else {
- if err := valueTypeStack.popAndVerifyType(refType); err != nil {
- return fmt.Errorf("cannot pop the operand for table.set: %v", err)
- }
- if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for table.set: %v", err)
- }
- }
- pc += num - 1
- } else if op == OpcodeMiscPrefix {
- pc++
- // A misc opcode is encoded as an unsigned variable 32-bit integer.
- miscOp32, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read misc opcode: %v", err)
- }
- pc += num - 1
- miscOpcode := byte(miscOp32)
- // If the misc opcode is beyond byte range, it is highly likely this is an invalid binary, or
- // it is due to the new opcode from a new proposal. In the latter case, we have to
- // change the alias type of OpcodeMisc (which is currently byte) to uint32.
- if uint32(byte(miscOp32)) != miscOp32 {
- return fmt.Errorf("invalid misc opcode: %#x", miscOp32)
- }
- if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureNonTrappingFloatToIntConversion); err != nil {
- return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
- }
- var inType, outType ValueType
- switch miscOpcode {
- case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U:
- inType, outType = ValueTypeF32, ValueTypeI32
- case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U:
- inType, outType = ValueTypeF64, ValueTypeI32
- case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U:
- inType, outType = ValueTypeF32, ValueTypeI64
- case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U:
- inType, outType = ValueTypeF64, ValueTypeI64
- }
- if err := valueTypeStack.popAndVerifyType(inType); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
- }
- valueTypeStack.push(outType)
- } else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
- return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
- }
- var params []ValueType
- // Handle opcodes added in bulk-memory-operations/WebAssembly 2.0.
- switch miscOpcode {
- case OpcodeMiscDataDrop:
- if m.DataCountSection == nil {
- return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
- }
-
- // We need to read the index to the data section.
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if int(index) >= len(m.DataSection) {
- return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
- }
- pc += num - 1
- case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill:
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode))
- }
- params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
-
- if miscOpcode == OpcodeMiscMemoryInit {
- if m.DataCountSection == nil {
- return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
- }
-
- // We need to read the index to the data section.
- pc++
- index, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if int(index) >= len(m.DataSection) {
- return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
- }
- pc += num - 1
- }
-
- pc++
- val, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if val != 0 || num != 1 {
- return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
- }
- if miscOpcode == OpcodeMiscMemoryCopy {
- pc++
- // memory.copy needs two memory index which are reserved as zero.
- val, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if val != 0 || num != 1 {
- return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
- }
- }
-
- case OpcodeMiscTableInit:
- params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
- pc++
- elementIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if int(elementIndex) >= len(m.ElementSection) {
- return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
- }
- pc += num
-
- tableIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if tableIndex != 0 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
- }
- }
- if tableIndex >= uint32(len(tables)) {
- return fmt.Errorf("table of index %d not found", tableIndex)
- }
-
- if m.ElementSection[elementIndex].Type != tables[tableIndex].Type {
- return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s",
- RefTypeName(m.ElementSection[elementIndex].Type),
- RefTypeName(tables[tableIndex].Type),
- )
- }
- pc += num - 1
- case OpcodeMiscElemDrop:
- pc++
- elementIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
- } else if int(elementIndex) >= len(m.ElementSection) {
- return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
- }
- pc += num - 1
- case OpcodeMiscTableCopy:
- params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
- pc++
-
- dstTableIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if dstTableIndex != 0 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
- }
- }
- if dstTableIndex >= uint32(len(tables)) {
- return fmt.Errorf("table of index %d not found", dstTableIndex)
- }
- pc += num
-
- srcTableIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if srcTableIndex != 0 {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
- }
- }
- if srcTableIndex >= uint32(len(tables)) {
- return fmt.Errorf("table of index %d not found", srcTableIndex)
- }
-
- if tables[srcTableIndex].Type != tables[dstTableIndex].Type {
- return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)",
- RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type))
- }
-
- pc += num - 1
- }
- for _, p := range params {
- if err := valueTypeStack.popAndVerifyType(p); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
- }
- }
- } else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
- }
-
- pc++
- tableIndex, num, err := leb128.LoadUint32(body[pc:])
- if err != nil {
- return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err)
- }
- if tableIndex >= uint32(len(tables)) {
- return fmt.Errorf("table of index %d not found", tableIndex)
- }
- pc += num - 1
-
- var params, results []ValueType
- reftype := tables[tableIndex].Type
- if miscOpcode == OpcodeMiscTableGrow {
- params = []ValueType{ValueTypeI32, reftype}
- results = []ValueType{ValueTypeI32}
- } else if miscOpcode == OpcodeMiscTableSize {
- results = []ValueType{ValueTypeI32}
- } else if miscOpcode == OpcodeMiscTableFill {
- params = []ValueType{ValueTypeI32, reftype, ValueTypeI32}
- }
-
- for _, p := range params {
- if err := valueTypeStack.popAndVerifyType(p); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
- }
- }
- for _, r := range results {
- valueTypeStack.push(r)
- }
- } else {
- return fmt.Errorf("unknown misc opcode %#x", miscOpcode)
- }
- } else if op == OpcodeVecPrefix {
- pc++
- // Vector instructions come with two bytes where the first byte is always OpcodeVecPrefix,
- // and the second byte determines the actual instruction.
- vecOpcode := body[pc]
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil {
- return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err)
- }
-
- switch vecOpcode {
- case OpcodeVecV128Const:
- // Read 128-bit = 16 bytes constants
- if int(pc+16) >= len(body) {
- return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode])
- }
- pc += 16
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue,
- OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
- OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat,
- OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat,
- OpcodeVecV128Load32zero, OpcodeVecV128Load64zero:
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
- }
- pc++
- align, _, read, err := readMemArg(pc, body)
- if err != nil {
- return err
- }
- pc += read - 1
- var maxAlign uint32
- switch vecOpcode {
- case OpcodeVecV128Load:
- maxAlign = 128 / 8
- case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
- OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u:
- maxAlign = 64 / 8
- case OpcodeVecV128Load8Splat:
- maxAlign = 1
- case OpcodeVecV128Load16Splat:
- maxAlign = 16 / 8
- case OpcodeVecV128Load32Splat:
- maxAlign = 32 / 8
- case OpcodeVecV128Load64Splat:
- maxAlign = 64 / 8
- case OpcodeVecV128Load32zero:
- maxAlign = 32 / 8
- case OpcodeVecV128Load64zero:
- maxAlign = 64 / 8
- }
-
- if 1<<align > maxAlign {
- return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode))
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecV128Store:
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
- }
- pc++
- align, _, read, err := readMemArg(pc, body)
- if err != nil {
- return err
- }
- pc += read - 1
- if 1<<align > 128/8 {
- return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
- }
- case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane:
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
- }
- attr := vecLoadLanes[vecOpcode]
- pc++
- align, _, read, err := readMemArg(pc, body)
- if err != nil {
- return err
- }
- if 1<<align > attr.alignMax {
- return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
- }
- pc += read
- if pc >= uint64(len(body)) {
- return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName)
- }
- lane := body[pc]
- if lane >= attr.laneCeil {
- return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane:
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
- }
- attr := vecStoreLanes[vecOpcode]
- pc++
- align, _, read, err := readMemArg(pc, body)
- if err != nil {
- return err
- }
- if 1<<align > attr.alignMax {
- return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
- }
- pc += read
- if pc >= uint64(len(body)) {
- return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
- }
- lane := body[pc]
- if lane >= attr.laneCeil {
- return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- case OpcodeVecI8x16ExtractLaneS,
- OpcodeVecI8x16ExtractLaneU,
- OpcodeVecI16x8ExtractLaneS,
- OpcodeVecI16x8ExtractLaneU,
- OpcodeVecI32x4ExtractLane,
- OpcodeVecI64x2ExtractLane,
- OpcodeVecF32x4ExtractLane,
- OpcodeVecF64x2ExtractLane:
- pc++
- if pc >= uint64(len(body)) {
- return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
- }
- attr := vecExtractLanes[vecOpcode]
- lane := body[pc]
- if lane >= attr.laneCeil {
- return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(attr.resultType)
- case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane,
- OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane:
- pc++
- if pc >= uint64(len(body)) {
- return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
- }
- attr := vecReplaceLanes[vecOpcode]
- lane := body[pc]
- if lane >= attr.laneCeil {
- return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
- }
- if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat,
- OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat:
- tp := vecSplatValueTypes[vecOpcode]
- if err := valueTypeStack.popAndVerifyType(tp); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecV128Bitselect:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecV128Not:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecV128i8x16Shuffle:
- pc++
- if pc+15 >= uint64(len(body)) {
- return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode])
- }
- lanes := body[pc : pc+16]
- for i, l := range lanes {
- if l >= 32 {
- return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode])
- }
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- pc += 15
- case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU,
- OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU,
- OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU,
- OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU:
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS,
- OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU,
- OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS,
- OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU,
- OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS,
- OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU,
- OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS,
- OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt,
- OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt,
- OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge,
- OpcodeVecI32x4DotI16x8S,
- OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg,
- OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt,
- OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs,
- OpcodeVecF32x4Abs, OpcodeVecF64x2Abs,
- OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest,
- OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest,
- OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U,
- OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U,
- OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U,
- OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U,
- OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U,
- OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero,
- OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U,
- OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U,
- OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
-
- case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU,
- OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul,
- OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul,
- OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul,
- OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div,
- OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div,
- OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU,
- OpcodeVecI8x16AvgrU,
- OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU,
- OpcodeVecI16x8AvgrU,
- OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU,
- OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max,
- OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax,
- OpcodeVecI16x8Q15mulrSatS,
- OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U,
- OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U,
- OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U:
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
- return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
- }
- valueTypeStack.push(ValueTypeV128)
- default:
- return fmt.Errorf("unknown SIMD instruction %s", vectorInstructionName[vecOpcode])
- }
- } else if op == OpcodeBlock {
- br.Reset(body[pc+1:])
- bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
- if err != nil {
- return fmt.Errorf("read block: %w", err)
- }
- controlBlockStack.push(pc, 0, 0, bt, num, 0)
- if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
- return err
- }
- // Plus we have to push any block params again.
- for _, p := range bt.Params {
- valueTypeStack.push(p)
- }
- valueTypeStack.pushStackLimit(len(bt.Params))
- pc += num
- } else if op == OpcodeAtomicPrefix {
- pc++
- // Atomic instructions come with two bytes where the first byte is always OpcodeAtomicPrefix,
- // and the second byte determines the actual instruction.
- atomicOpcode := body[pc]
- if err := enabledFeatures.RequireEnabled(experimental.CoreFeaturesThreads); err != nil {
- return fmt.Errorf("%s invalid as %v", atomicInstructionName[atomicOpcode], err)
- }
- pc++
-
- if atomicOpcode == OpcodeAtomicFence {
- // No memory requirement and no arguments or return, however the immediate byte value must be 0.
- imm := body[pc]
- if imm != 0x0 {
- return fmt.Errorf("invalid immediate value for %s", AtomicInstructionName(atomicOpcode))
- }
- continue
- }
-
- // All atomic operations except fence (checked above) require memory
- if memory == nil {
- return fmt.Errorf("memory must exist for %s", AtomicInstructionName(atomicOpcode))
- }
- align, _, read, err := readMemArg(pc, body)
- if err != nil {
- return err
- }
- pc += read - 1
- switch atomicOpcode {
- case OpcodeAtomicMemoryNotify:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicMemoryWait32:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicMemoryWait64:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI32Load:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI64Load:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI32Load8U:
- if 1<<align != 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI32Load16U:
- if 1<<align != 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI64Load8U:
- if 1<<align != 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Load16U:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Load32U:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI32Store:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI64Store:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI32Store8:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI32Store16:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI64Store8:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI64Store16:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI64Store32:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- case OpcodeAtomicI32RmwAdd, OpcodeAtomicI32RmwSub, OpcodeAtomicI32RmwAnd, OpcodeAtomicI32RmwOr, OpcodeAtomicI32RmwXor, OpcodeAtomicI32RmwXchg:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI32Rmw8AddU, OpcodeAtomicI32Rmw8SubU, OpcodeAtomicI32Rmw8AndU, OpcodeAtomicI32Rmw8OrU, OpcodeAtomicI32Rmw8XorU, OpcodeAtomicI32Rmw8XchgU:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI32Rmw16AddU, OpcodeAtomicI32Rmw16SubU, OpcodeAtomicI32Rmw16AndU, OpcodeAtomicI32Rmw16OrU, OpcodeAtomicI32Rmw16XorU, OpcodeAtomicI32Rmw16XchgU:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI64RmwAdd, OpcodeAtomicI64RmwSub, OpcodeAtomicI64RmwAnd, OpcodeAtomicI64RmwOr, OpcodeAtomicI64RmwXor, OpcodeAtomicI64RmwXchg:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Rmw8AddU, OpcodeAtomicI64Rmw8SubU, OpcodeAtomicI64Rmw8AndU, OpcodeAtomicI64Rmw8OrU, OpcodeAtomicI64Rmw8XorU, OpcodeAtomicI64Rmw8XchgU:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Rmw16AddU, OpcodeAtomicI64Rmw16SubU, OpcodeAtomicI64Rmw16AndU, OpcodeAtomicI64Rmw16OrU, OpcodeAtomicI64Rmw16XorU, OpcodeAtomicI64Rmw16XchgU:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Rmw32AddU, OpcodeAtomicI64Rmw32SubU, OpcodeAtomicI64Rmw32AndU, OpcodeAtomicI64Rmw32OrU, OpcodeAtomicI64Rmw32XorU, OpcodeAtomicI64Rmw32XchgU:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI32RmwCmpxchg:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI32Rmw8CmpxchgU:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI32Rmw16CmpxchgU:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI32)
- case OpcodeAtomicI64RmwCmpxchg:
- if 1<<align > 64/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Rmw8CmpxchgU:
- if 1<<align > 1 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Rmw16CmpxchgU:
- if 1<<align > 16/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- case OpcodeAtomicI64Rmw32CmpxchgU:
- if 1<<align > 32/8 {
- return fmt.Errorf("invalid memory alignment")
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
- return err
- }
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return err
- }
- valueTypeStack.push(ValueTypeI64)
- default:
- return fmt.Errorf("invalid atomic opcode: 0x%x", atomicOpcode)
- }
- } else if op == OpcodeLoop {
- br.Reset(body[pc+1:])
- bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
- if err != nil {
- return fmt.Errorf("read block: %w", err)
- }
- controlBlockStack.push(pc, 0, 0, bt, num, op)
- if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
- return err
- }
- // Plus we have to push any block params again.
- for _, p := range bt.Params {
- valueTypeStack.push(p)
- }
- valueTypeStack.pushStackLimit(len(bt.Params))
- pc += num
- } else if op == OpcodeIf {
- br.Reset(body[pc+1:])
- bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
- if err != nil {
- return fmt.Errorf("read block: %w", err)
- }
- controlBlockStack.push(pc, 0, 0, bt, num, op)
- if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("cannot pop the operand for 'if': %v", err)
- }
- if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
- return err
- }
- // Plus we have to push any block params again.
- for _, p := range bt.Params {
- valueTypeStack.push(p)
- }
- valueTypeStack.pushStackLimit(len(bt.Params))
- pc += num
- } else if op == OpcodeElse {
- bl := &controlBlockStack.stack[len(controlBlockStack.stack)-1]
- if bl.op != OpcodeIf {
- return fmt.Errorf("else instruction must be used in if block: %#x", pc)
- }
- bl.op = OpcodeElse
- bl.elseAt = pc
- // Check the type soundness of the instructions *before* entering this else Op.
- if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil {
- return err
- }
- // Before entering instructions inside else, we pop all the values pushed by then block.
- valueTypeStack.resetAtStackLimit()
- // Plus we have to push any block params again.
- for _, p := range bl.blockType.Params {
- valueTypeStack.push(p)
- }
- } else if op == OpcodeEnd {
- bl := controlBlockStack.pop()
- bl.endAt = pc
-
- // OpcodeEnd can end a block or the function itself. Check to see what it is:
-
- ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt
- if ifMissingElse {
- // If this is the end of block without else, the number of block's results and params must be same.
- // Otherwise, the value stack would result in the inconsistent state at runtime.
- if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) {
- return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results)
- }
- // -1 skips else, to handle if block without else properly.
- bl.elseAt = bl.endAt - 1
- }
-
- // Determine the block context
- ctx := "" // the outer-most block: the function return
- if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 {
- ctx = OpcodeElseName
- } else if bl.op != 0 {
- ctx = InstructionName(bl.op)
- }
-
- // Check return types match
- if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil {
- return err
- }
-
- // Put the result types at the end after resetting at the stack limit
- // since we might have Any type between the limit and the current top.
- valueTypeStack.resetAtStackLimit()
- for _, exp := range bl.blockType.Results {
- valueTypeStack.push(exp)
- }
- // We exit if/loop/block, so reset the constraints on the stack manipulation
- // on values previously pushed by outer blocks.
- valueTypeStack.popStackLimit()
- } else if op == OpcodeReturn {
- // Same formatting as OpcodeEnd on the outer-most block
- if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil {
- return err
- }
- // return instruction is stack-polymorphic.
- valueTypeStack.unreachable()
- } else if op == OpcodeDrop {
- _, err := valueTypeStack.pop()
- if err != nil {
- return fmt.Errorf("invalid drop: %v", err)
- }
- } else if op == OpcodeSelect || op == OpcodeTypedSelect {
- if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
- return fmt.Errorf("type mismatch on 3rd select operand: %v", err)
- }
- v1, err := valueTypeStack.pop()
- if err != nil {
- return fmt.Errorf("invalid select: %v", err)
- }
- v2, err := valueTypeStack.pop()
- if err != nil {
- return fmt.Errorf("invalid select: %v", err)
- }
-
- if op == OpcodeTypedSelect {
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
- return fmt.Errorf("%s is invalid as %w", InstructionName(op), err)
- }
- pc++
- if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 {
- return fmt.Errorf("too many type immediates for %s", InstructionName(op))
- }
- pc++
- tp := body[pc]
- if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 &&
- tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 {
- return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName)
- }
- } else if isReferenceValueType(v1) || isReferenceValueType(v2) {
- return fmt.Errorf("reference types cannot be used for non typed select instruction")
- }
-
- if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown {
- return fmt.Errorf("type mismatch on 1st and 2nd select operands")
- }
- if v1 == valueTypeUnknown {
- valueTypeStack.push(v2)
- } else {
- valueTypeStack.push(v1)
- }
- } else if op == OpcodeUnreachable {
- // unreachable instruction is stack-polymorphic.
- valueTypeStack.unreachable()
- } else if op == OpcodeNop {
- } else {
- return fmt.Errorf("invalid instruction 0x%x", op)
- }
- }
-
- if len(controlBlockStack.stack) > 0 {
- return fmt.Errorf("ill-nested block exists")
- }
- if valueTypeStack.maximumStackPointer > maxStackValues {
- return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues)
- }
- return nil
-}
-
-var vecExtractLanes = [...]struct {
- laneCeil byte
- resultType ValueType
-}{
- OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32},
- OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32},
- OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32},
- OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32},
- OpcodeVecI32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeI32},
- OpcodeVecI64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeI64},
- OpcodeVecF32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeF32},
- OpcodeVecF64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeF64},
-}
-
-var vecReplaceLanes = [...]struct {
- laneCeil byte
- paramType ValueType
-}{
- OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32},
- OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32},
- OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32},
- OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64},
- OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32},
- OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64},
-}
-
-var vecStoreLanes = [...]struct {
- alignMax uint32
- laneCeil byte
-}{
- OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
- OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
- OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
- OpcodeVecV128Store8Lane: {alignMax: 1, laneCeil: 128 / 8},
-}
-
-var vecLoadLanes = [...]struct {
- alignMax uint32
- laneCeil byte
-}{
- OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
- OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
- OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
- OpcodeVecV128Load8Lane: {alignMax: 1, laneCeil: 128 / 8},
-}
-
-var vecSplatValueTypes = [...]ValueType{
- OpcodeVecI8x16Splat: ValueTypeI32,
- OpcodeVecI16x8Splat: ValueTypeI32,
- OpcodeVecI32x4Splat: ValueTypeI32,
- OpcodeVecI64x2Splat: ValueTypeI64,
- OpcodeVecF32x4Splat: ValueTypeF32,
- OpcodeVecF64x2Splat: ValueTypeF64,
-}
-
-type stacks struct {
- vs valueTypeStack
- cs controlBlockStack
- // ls is the label slice that is reused for each br_table instruction.
- ls []uint32
-}
-
-func (sts *stacks) reset(functionType *FunctionType) {
- // Reset valueStack for reuse.
- sts.vs.stack = sts.vs.stack[:0]
- sts.vs.stackLimits = sts.vs.stackLimits[:0]
- sts.vs.maximumStackPointer = 0
- sts.cs.stack = sts.cs.stack[:0]
- sts.cs.stack = append(sts.cs.stack, controlBlock{blockType: functionType})
- sts.ls = sts.ls[:0]
-}
-
-type controlBlockStack struct {
- stack []controlBlock
-}
-
-func (s *controlBlockStack) pop() *controlBlock {
- tail := len(s.stack) - 1
- ret := &s.stack[tail]
- s.stack = s.stack[:tail]
- return ret
-}
-
-func (s *controlBlockStack) push(startAt, elseAt, endAt uint64, blockType *FunctionType, blockTypeBytes uint64, op Opcode) {
- s.stack = append(s.stack, controlBlock{
- startAt: startAt,
- elseAt: elseAt,
- endAt: endAt,
- blockType: blockType,
- blockTypeBytes: blockTypeBytes,
- op: op,
- })
-}
-
-type valueTypeStack struct {
- stack []ValueType
- stackLimits []int
- maximumStackPointer int
- // requireStackValuesTmp is used in requireStackValues function to reduce the allocation.
- requireStackValuesTmp []ValueType
-}
-
-// Only used in the analyzeFunction below.
-const valueTypeUnknown = ValueType(0xFF)
-
-func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) {
- if len(s.stackLimits) > 0 {
- limit = s.stackLimits[len(s.stackLimits)-1]
- }
- stackLen := len(s.stack)
- if stackLen <= limit {
- return
- } else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown {
- vt = valueTypeUnknown
- ok = true
- return
- } else {
- vt = s.stack[stackLen-1]
- s.stack = s.stack[:stackLen-1]
- ok = true
- return
- }
-}
-
-func (s *valueTypeStack) pop() (ValueType, error) {
- if vt, limit, ok := s.tryPop(); ok {
- return vt, nil
- } else {
- return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit)
- }
-}
-
-// popAndVerifyType returns an error if the stack value is unexpected.
-func (s *valueTypeStack) popAndVerifyType(expected ValueType) error {
- have, _, ok := s.tryPop()
- if !ok {
- return fmt.Errorf("%s missing", ValueTypeName(expected))
- }
- if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown {
- return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have))
- }
- return nil
-}
-
-func (s *valueTypeStack) push(v ValueType) {
- s.stack = append(s.stack, v)
- if sp := len(s.stack); sp > s.maximumStackPointer {
- s.maximumStackPointer = sp
- }
-}
-
-func (s *valueTypeStack) unreachable() {
- s.resetAtStackLimit()
- s.stack = append(s.stack, valueTypeUnknown)
-}
-
-func (s *valueTypeStack) resetAtStackLimit() {
- if len(s.stackLimits) != 0 {
- s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]]
- } else {
- s.stack = s.stack[:0]
- }
-}
-
-func (s *valueTypeStack) popStackLimit() {
- if len(s.stackLimits) != 0 {
- s.stackLimits = s.stackLimits[:len(s.stackLimits)-1]
- }
-}
-
-// pushStackLimit pushes the control frame's bottom of the stack.
-func (s *valueTypeStack) pushStackLimit(params int) {
- limit := len(s.stack) - params
- s.stackLimits = append(s.stackLimits, limit)
-}
-
-func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error {
- return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit)
-}
-
-func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error {
- return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit)
-}
-
-func (s *valueTypeStack) requireStackValues(
- isParam bool,
- context string,
- want []ValueType,
- checkAboveLimit bool,
-) error {
- limit := 0
- if len(s.stackLimits) > 0 {
- limit = s.stackLimits[len(s.stackLimits)-1]
- }
- // Iterate backwards as we are comparing the desired slice against stack value types.
- countWanted := len(want)
-
- // First, check if there are enough values on the stack.
- s.requireStackValuesTmp = s.requireStackValuesTmp[:0]
- for i := countWanted - 1; i >= 0; i-- {
- popped, _, ok := s.tryPop()
- if !ok {
- if len(s.requireStackValuesTmp) > len(want) {
- return typeCountError(isParam, context, s.requireStackValuesTmp, want)
- }
- return typeCountError(isParam, context, s.requireStackValuesTmp, want)
- }
- s.requireStackValuesTmp = append(s.requireStackValuesTmp, popped)
- }
-
- // Now, check if there are too many values.
- if checkAboveLimit {
- if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) {
- return typeCountError(isParam, context, append(s.stack, want...), want)
- }
- }
-
- // Finally, check the types of the values:
- for i, v := range s.requireStackValuesTmp {
- nextWant := want[countWanted-i-1] // have is in reverse order (stack)
- if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown {
- return typeMismatchError(isParam, context, v, nextWant, i)
- }
- }
- return nil
-}
-
-// typeMismatchError returns an error similar to go compiler's error on type mismatch.
-func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error {
- var ret strings.Builder
- ret.WriteString("cannot use ")
- ret.WriteString(ValueTypeName(have))
- if context != "" {
- ret.WriteString(" in ")
- ret.WriteString(context)
- ret.WriteString(" block")
- }
- if isParam {
- ret.WriteString(" as param")
- } else {
- ret.WriteString(" as result")
- }
- ret.WriteString("[")
- ret.WriteString(strconv.Itoa(i))
- ret.WriteString("] type ")
- ret.WriteString(ValueTypeName(want))
- return errors.New(ret.String())
-}
-
-// typeCountError returns an error similar to go compiler's error on type count mismatch.
-func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error {
- var ret strings.Builder
- if len(have) > len(want) {
- ret.WriteString("too many ")
- } else {
- ret.WriteString("not enough ")
- }
- if isParam {
- ret.WriteString("params")
- } else {
- ret.WriteString("results")
- }
- if context != "" {
- if isParam {
- ret.WriteString(" for ")
- } else {
- ret.WriteString(" in ")
- }
- ret.WriteString(context)
- ret.WriteString(" block")
- }
- ret.WriteString("\n\thave (")
- writeValueTypes(have, &ret)
- ret.WriteString(")\n\twant (")
- writeValueTypes(want, &ret)
- ret.WriteByte(')')
- return errors.New(ret.String())
-}
-
-func writeValueTypes(vts []ValueType, ret *strings.Builder) {
- switch len(vts) {
- case 0:
- case 1:
- ret.WriteString(ValueTypeName(vts[0]))
- default:
- ret.WriteString(ValueTypeName(vts[0]))
- for _, vt := range vts[1:] {
- ret.WriteString(", ")
- ret.WriteString(ValueTypeName(vt))
- }
- }
-}
-
-func (s *valueTypeStack) String() string {
- var typeStrs, limits []string
- for _, v := range s.stack {
- var str string
- if v == valueTypeUnknown {
- str = "unknown"
- } else {
- str = ValueTypeName(v)
- }
- typeStrs = append(typeStrs, str)
- }
- for _, d := range s.stackLimits {
- limits = append(limits, fmt.Sprintf("%d", d))
- }
- return fmt.Sprintf("{stack: [%s], limits: [%s]}",
- strings.Join(typeStrs, ", "), strings.Join(limits, ","))
-}
-
-type controlBlock struct {
- startAt, elseAt, endAt uint64
- blockType *FunctionType
- blockTypeBytes uint64
- // op is zero when the outermost block
- op Opcode
-}
-
-// DecodeBlockType decodes the type index from a positive 33-bit signed integer. Negative numbers indicate up to one
-// WebAssembly 1.0 (20191205) compatible result type. Positive numbers are decoded when `enabledFeatures` include
-// CoreFeatureMultiValue 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/wg-2.0.draft1/proposals/multi-value/Overview.md
-func DecodeBlockType(types []FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) {
- raw, num, err := leb128.DecodeInt33AsInt64(r)
- if err != nil {
- return nil, 0, fmt.Errorf("decode int33: %w", err)
- }
-
- var ret *FunctionType
- switch raw {
- case -64: // 0x40 in original byte = nil
- ret = blockType_v_v
- case -1: // 0x7f in original byte = i32
- ret = blockType_v_i32
- case -2: // 0x7e in original byte = i64
- ret = blockType_v_i64
- case -3: // 0x7d in original byte = f32
- ret = blockType_v_f32
- case -4: // 0x7c in original byte = f64
- ret = blockType_v_f64
- case -5: // 0x7b in original byte = v128
- ret = blockType_v_v128
- case -16: // 0x70 in original byte = funcref
- ret = blockType_v_funcref
- case -17: // 0x6f in original byte = externref
- ret = blockType_v_externref
- default:
- if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
- return nil, num, fmt.Errorf("block with function type return invalid as %v", err)
- }
- if raw < 0 || (raw >= int64(len(types))) {
- return nil, 0, fmt.Errorf("type index out of range: %d", raw)
- }
- ret = &types[raw]
- }
- return ret, num, err
-}
-
-// These block types are defined as globals in order to avoid allocations in DecodeBlockType.
-var (
- blockType_v_v = &FunctionType{}
- blockType_v_i32 = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1}
- blockType_v_i64 = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1}
- blockType_v_f32 = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1}
- blockType_v_f64 = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1}
- blockType_v_v128 = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2}
- blockType_v_funcref = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1}
- blockType_v_externref = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1}
-)
-
-// SplitCallStack returns the input stack resliced to the count of params and
-// results, or errors if it isn't long enough for either.
-func SplitCallStack(ft *FunctionType, stack []uint64) (params []uint64, results []uint64, err error) {
- stackLen := len(stack)
- if n := ft.ParamNumInUint64; n > stackLen {
- return nil, nil, fmt.Errorf("need %d params, but stack size is %d", n, stackLen)
- } else if n > 0 {
- params = stack[:n]
- }
- if n := ft.ResultNumInUint64; n > stackLen {
- return nil, nil, fmt.Errorf("need %d results, but stack size is %d", n, stackLen)
- } else if n > 0 {
- results = stack[:n]
- }
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go
deleted file mode 100644
index c5f6e9121..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/function_definition.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package wasm
-
-import (
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/internalapi"
- "github.com/tetratelabs/wazero/internal/wasmdebug"
-)
-
-// ImportedFunctions returns the definitions of each imported function.
-//
-// Note: Unlike ExportedFunctions, there is no unique constraint on imports.
-func (m *Module) ImportedFunctions() (ret []api.FunctionDefinition) {
- for i := uint32(0); i < m.ImportFunctionCount; i++ {
- ret = append(ret, m.FunctionDefinition(i))
- }
- return
-}
-
-// ExportedFunctions returns the definitions of each exported function.
-func (m *Module) ExportedFunctions() map[string]api.FunctionDefinition {
- ret := map[string]api.FunctionDefinition{}
- for i := range m.ExportSection {
- exp := &m.ExportSection[i]
- if exp.Type == ExternTypeFunc {
- d := m.FunctionDefinition(exp.Index)
- ret[exp.Name] = d
- }
- }
- return ret
-}
-
-// FunctionDefinition returns the FunctionDefinition for the given `index`.
-func (m *Module) FunctionDefinition(index Index) *FunctionDefinition {
- // TODO: function initialization is lazy, but bulk. Make it per function.
- m.buildFunctionDefinitions()
- return &m.FunctionDefinitionSection[index]
-}
-
-// buildFunctionDefinitions generates function metadata that can be parsed from
-// the module. This must be called after all validation.
-func (m *Module) buildFunctionDefinitions() {
- m.functionDefinitionSectionInitOnce.Do(m.buildFunctionDefinitionsOnce)
-}
-
-func (m *Module) buildFunctionDefinitionsOnce() {
- var moduleName string
- var functionNames NameMap
- var localNames, resultNames IndirectNameMap
- if m.NameSection != nil {
- moduleName = m.NameSection.ModuleName
- functionNames = m.NameSection.FunctionNames
- localNames = m.NameSection.LocalNames
- resultNames = m.NameSection.ResultNames
- }
-
- importCount := m.ImportFunctionCount
- m.FunctionDefinitionSection = make([]FunctionDefinition, importCount+uint32(len(m.FunctionSection)))
-
- importFuncIdx := Index(0)
- for i := range m.ImportSection {
- imp := &m.ImportSection[i]
- if imp.Type != ExternTypeFunc {
- continue
- }
-
- def := &m.FunctionDefinitionSection[importFuncIdx]
- def.importDesc = imp
- def.index = importFuncIdx
- def.Functype = &m.TypeSection[imp.DescFunc]
- importFuncIdx++
- }
-
- for codeIndex, typeIndex := range m.FunctionSection {
- code := &m.CodeSection[codeIndex]
- idx := importFuncIdx + Index(codeIndex)
- def := &m.FunctionDefinitionSection[idx]
- def.index = idx
- def.Functype = &m.TypeSection[typeIndex]
- def.goFunc = code.GoFunc
- }
-
- n, nLen := 0, len(functionNames)
- for i := range m.FunctionDefinitionSection {
- d := &m.FunctionDefinitionSection[i]
- // The function name section begins with imports, but can be sparse.
- // This keeps track of how far in the name section we've searched.
- funcIdx := d.index
- var funcName string
- for ; n < nLen; n++ {
- next := &functionNames[n]
- if next.Index > funcIdx {
- break // we have function names, but starting at a later index.
- } else if next.Index == funcIdx {
- funcName = next.Name
- break
- }
- }
-
- d.moduleName = moduleName
- d.name = funcName
- d.Debugname = wasmdebug.FuncName(moduleName, funcName, funcIdx)
- d.paramNames = paramNames(localNames, funcIdx, len(d.Functype.Params))
- d.resultNames = paramNames(resultNames, funcIdx, len(d.Functype.Results))
-
- for i := range m.ExportSection {
- e := &m.ExportSection[i]
- if e.Type == ExternTypeFunc && e.Index == funcIdx {
- d.exportNames = append(d.exportNames, e.Name)
- }
- }
- }
-}
-
-// FunctionDefinition implements api.FunctionDefinition
-type FunctionDefinition struct {
- internalapi.WazeroOnlyType
- moduleName string
- index Index
- name string
- // Debugname is exported for testing purpose.
- Debugname string
- goFunc interface{}
- // Functype is exported for testing purpose.
- Functype *FunctionType
- importDesc *Import
- exportNames []string
- paramNames []string
- resultNames []string
-}
-
-// ModuleName implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) ModuleName() string {
- return f.moduleName
-}
-
-// Index implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) Index() uint32 {
- return f.index
-}
-
-// Name implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) Name() string {
- return f.name
-}
-
-// DebugName implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) DebugName() string {
- return f.Debugname
-}
-
-// Import implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) Import() (moduleName, name string, isImport bool) {
- if f.importDesc != nil {
- importDesc := f.importDesc
- moduleName, name, isImport = importDesc.Module, importDesc.Name, true
- }
- return
-}
-
-// ExportNames implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) ExportNames() []string {
- return f.exportNames
-}
-
-// GoFunction implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) GoFunction() interface{} {
- return f.goFunc
-}
-
-// ParamTypes implements api.FunctionDefinition ParamTypes.
-func (f *FunctionDefinition) ParamTypes() []ValueType {
- return f.Functype.Params
-}
-
-// ParamNames implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) ParamNames() []string {
- return f.paramNames
-}
-
-// ResultTypes implements api.FunctionDefinition ResultTypes.
-func (f *FunctionDefinition) ResultTypes() []ValueType {
- return f.Functype.Results
-}
-
-// ResultNames implements the same method as documented on api.FunctionDefinition.
-func (f *FunctionDefinition) ResultNames() []string {
- return f.resultNames
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/global.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/global.go
deleted file mode 100644
index abaa2d1f9..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/global.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package wasm
-
-import (
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/internalapi"
-)
-
-// constantGlobal wraps GlobalInstance to implement api.Global.
-type constantGlobal struct {
- internalapi.WazeroOnlyType
- g *GlobalInstance
-}
-
-// Type implements api.Global.
-func (g constantGlobal) Type() api.ValueType {
- return g.g.Type.ValType
-}
-
-// Get implements api.Global.
-func (g constantGlobal) Get() uint64 {
- ret, _ := g.g.Value()
- return ret
-}
-
-// String implements api.Global.
-func (g constantGlobal) String() string {
- return g.g.String()
-}
-
-// mutableGlobal extends constantGlobal to allow updates.
-type mutableGlobal struct {
- internalapi.WazeroOnlyType
- g *GlobalInstance
-}
-
-// Type implements api.Global.
-func (g mutableGlobal) Type() api.ValueType {
- return g.g.Type.ValType
-}
-
-// Get implements api.Global.
-func (g mutableGlobal) Get() uint64 {
- ret, _ := g.g.Value()
- return ret
-}
-
-// String implements api.Global.
-func (g mutableGlobal) String() string {
- return g.g.String()
-}
-
-// Set implements the same method as documented on api.MutableGlobal.
-func (g mutableGlobal) Set(v uint64) {
- g.g.SetValue(v, 0)
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go
deleted file mode 100644
index 9510c2588..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/gofunc.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package wasm
-
-import (
- "bytes"
- "context"
- "errors"
- "fmt"
- "math"
- "reflect"
-
- "github.com/tetratelabs/wazero/api"
-)
-
-type paramsKind byte
-
-const (
- paramsKindNoContext paramsKind = iota
- paramsKindContext
- paramsKindContextModule
-)
-
-// Below are reflection code to get the interface type used to parse functions and set values.
-
-var (
- moduleType = reflect.TypeOf((*api.Module)(nil)).Elem()
- goContextType = reflect.TypeOf((*context.Context)(nil)).Elem()
- errorType = reflect.TypeOf((*error)(nil)).Elem()
-)
-
-// compile-time check to ensure reflectGoModuleFunction implements
-// api.GoModuleFunction.
-var _ api.GoModuleFunction = (*reflectGoModuleFunction)(nil)
-
-type reflectGoModuleFunction struct {
- fn *reflect.Value
- params, results []ValueType
-}
-
-// Call implements the same method as documented on api.GoModuleFunction.
-func (f *reflectGoModuleFunction) Call(ctx context.Context, mod api.Module, stack []uint64) {
- callGoFunc(ctx, mod, f.fn, stack)
-}
-
-// EqualTo is exposed for testing.
-func (f *reflectGoModuleFunction) EqualTo(that interface{}) bool {
- if f2, ok := that.(*reflectGoModuleFunction); !ok {
- return false
- } else {
- // TODO compare reflect pointers
- return bytes.Equal(f.params, f2.params) && bytes.Equal(f.results, f2.results)
- }
-}
-
-// compile-time check to ensure reflectGoFunction implements api.GoFunction.
-var _ api.GoFunction = (*reflectGoFunction)(nil)
-
-type reflectGoFunction struct {
- fn *reflect.Value
- pk paramsKind
- params, results []ValueType
-}
-
-// EqualTo is exposed for testing.
-func (f *reflectGoFunction) EqualTo(that interface{}) bool {
- if f2, ok := that.(*reflectGoFunction); !ok {
- return false
- } else {
- // TODO compare reflect pointers
- return f.pk == f2.pk &&
- bytes.Equal(f.params, f2.params) && bytes.Equal(f.results, f2.results)
- }
-}
-
-// Call implements the same method as documented on api.GoFunction.
-func (f *reflectGoFunction) Call(ctx context.Context, stack []uint64) {
- if f.pk == paramsKindNoContext {
- ctx = nil
- }
- callGoFunc(ctx, nil, f.fn, stack)
-}
-
-// callGoFunc executes the reflective function by converting params to Go
-// types. The results of the function call are converted back to api.ValueType.
-func callGoFunc(ctx context.Context, mod api.Module, fn *reflect.Value, stack []uint64) {
- tp := fn.Type()
-
- var in []reflect.Value
- pLen := tp.NumIn()
- if pLen != 0 {
- in = make([]reflect.Value, pLen)
-
- i := 0
- if ctx != nil {
- in[0] = newContextVal(ctx)
- i++
- }
- if mod != nil {
- in[1] = newModuleVal(mod)
- i++
- }
-
- for j := 0; i < pLen; i++ {
- next := tp.In(i)
- val := reflect.New(next).Elem()
- k := next.Kind()
- raw := stack[j]
- j++
-
- switch k {
- case reflect.Float32:
- val.SetFloat(float64(math.Float32frombits(uint32(raw))))
- case reflect.Float64:
- val.SetFloat(math.Float64frombits(raw))
- case reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- val.SetUint(raw)
- case reflect.Int32, reflect.Int64:
- val.SetInt(int64(raw))
- default:
- panic(fmt.Errorf("BUG: param[%d] has an invalid type: %v", i, k))
- }
- in[i] = val
- }
- }
-
- // Execute the host function and push back the call result onto the stack.
- for i, ret := range fn.Call(in) {
- switch ret.Kind() {
- case reflect.Float32:
- stack[i] = uint64(math.Float32bits(float32(ret.Float())))
- case reflect.Float64:
- stack[i] = math.Float64bits(ret.Float())
- case reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- stack[i] = ret.Uint()
- case reflect.Int32, reflect.Int64:
- stack[i] = uint64(ret.Int())
- default:
- panic(fmt.Errorf("BUG: result[%d] has an invalid type: %v", i, ret.Kind()))
- }
- }
-}
-
-func newContextVal(ctx context.Context) reflect.Value {
- val := reflect.New(goContextType).Elem()
- val.Set(reflect.ValueOf(ctx))
- return val
-}
-
-func newModuleVal(m api.Module) reflect.Value {
- val := reflect.New(moduleType).Elem()
- val.Set(reflect.ValueOf(m))
- return val
-}
-
-// MustParseGoReflectFuncCode parses Code from the go function or panics.
-//
-// Exposing this simplifies FunctionDefinition of host functions in built-in host
-// modules and tests.
-func MustParseGoReflectFuncCode(fn interface{}) Code {
- _, _, code, err := parseGoReflectFunc(fn)
- if err != nil {
- panic(err)
- }
- return code
-}
-
-func parseGoReflectFunc(fn interface{}) (params, results []ValueType, code Code, err error) {
- fnV := reflect.ValueOf(fn)
- p := fnV.Type()
-
- if fnV.Kind() != reflect.Func {
- err = fmt.Errorf("kind != func: %s", fnV.Kind().String())
- return
- }
-
- pk, kindErr := kind(p)
- if kindErr != nil {
- err = kindErr
- return
- }
-
- pOffset := 0
- switch pk {
- case paramsKindNoContext:
- case paramsKindContext:
- pOffset = 1
- case paramsKindContextModule:
- pOffset = 2
- }
-
- pCount := p.NumIn() - pOffset
- if pCount > 0 {
- params = make([]ValueType, pCount)
- }
- for i := 0; i < len(params); i++ {
- pI := p.In(i + pOffset)
- if t, ok := getTypeOf(pI.Kind()); ok {
- params[i] = t
- continue
- }
-
- // Now, we will definitely err, decide which message is best
- var arg0Type reflect.Type
- if hc := pI.Implements(moduleType); hc {
- arg0Type = moduleType
- } else if gc := pI.Implements(goContextType); gc {
- arg0Type = goContextType
- }
-
- if arg0Type != nil {
- err = fmt.Errorf("param[%d] is a %s, which may be defined only once as param[0]", i+pOffset, arg0Type)
- } else {
- err = fmt.Errorf("param[%d] is unsupported: %s", i+pOffset, pI.Kind())
- }
- return
- }
-
- rCount := p.NumOut()
- if rCount > 0 {
- results = make([]ValueType, rCount)
- }
- for i := 0; i < len(results); i++ {
- rI := p.Out(i)
- if t, ok := getTypeOf(rI.Kind()); ok {
- results[i] = t
- continue
- }
-
- // Now, we will definitely err, decide which message is best
- if rI.Implements(errorType) {
- err = fmt.Errorf("result[%d] is an error, which is unsupported", i)
- } else {
- err = fmt.Errorf("result[%d] is unsupported: %s", i, rI.Kind())
- }
- return
- }
-
- code = Code{}
- if pk == paramsKindContextModule {
- code.GoFunc = &reflectGoModuleFunction{fn: &fnV, params: params, results: results}
- } else {
- code.GoFunc = &reflectGoFunction{pk: pk, fn: &fnV, params: params, results: results}
- }
- return
-}
-
-func kind(p reflect.Type) (paramsKind, error) {
- pCount := p.NumIn()
- if pCount > 0 && p.In(0).Kind() == reflect.Interface {
- p0 := p.In(0)
- if p0.Implements(moduleType) {
- return 0, errors.New("invalid signature: api.Module parameter must be preceded by context.Context")
- } else if p0.Implements(goContextType) {
- if pCount >= 2 && p.In(1).Implements(moduleType) {
- return paramsKindContextModule, nil
- }
- return paramsKindContext, nil
- }
- }
- // Without context param allows portability with reflective runtimes.
- // This allows people to more easily port to wazero.
- return paramsKindNoContext, nil
-}
-
-func getTypeOf(kind reflect.Kind) (ValueType, bool) {
- switch kind {
- case reflect.Float64:
- return ValueTypeF64, true
- case reflect.Float32:
- return ValueTypeF32, true
- case reflect.Int32, reflect.Uint32:
- return ValueTypeI32, true
- case reflect.Int64, reflect.Uint64:
- return ValueTypeI64, true
- case reflect.Uintptr:
- return ValueTypeExternref, true
- default:
- return 0x00, false
- }
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/host.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/host.go
deleted file mode 100644
index bca686d1d..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/host.go
+++ /dev/null
@@ -1,179 +0,0 @@
-package wasm
-
-import (
- "errors"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/wasmdebug"
-)
-
-type HostFuncExporter interface {
- ExportHostFunc(*HostFunc)
-}
-
-// HostFunc is a function with an inlined type, used for NewHostModule.
-// Any corresponding FunctionType will be reused or added to the Module.
-type HostFunc struct {
- // ExportName is the only value returned by api.FunctionDefinition.
- ExportName string
-
- // Name is equivalent to the same method on api.FunctionDefinition.
- Name string
-
- // ParamTypes is equivalent to the same method on api.FunctionDefinition.
- ParamTypes []ValueType
-
- // ParamNames is equivalent to the same method on api.FunctionDefinition.
- ParamNames []string
-
- // ResultTypes is equivalent to the same method on api.FunctionDefinition.
- ResultTypes []ValueType
-
- // ResultNames is equivalent to the same method on api.FunctionDefinition.
- ResultNames []string
-
- // Code is the equivalent function in the SectionIDCode.
- Code Code
-}
-
-// WithGoModuleFunc returns a copy of the function, replacing its Code.GoFunc.
-func (f *HostFunc) WithGoModuleFunc(fn api.GoModuleFunc) *HostFunc {
- ret := *f
- ret.Code.GoFunc = fn
- return &ret
-}
-
-// NewHostModule is defined internally for use in WASI tests and to keep the code size in the root directory small.
-func NewHostModule(
- moduleName string,
- exportNames []string,
- nameToHostFunc map[string]*HostFunc,
- enabledFeatures api.CoreFeatures,
-) (m *Module, err error) {
- if moduleName != "" {
- m = &Module{NameSection: &NameSection{ModuleName: moduleName}}
- } else {
- return nil, errors.New("a module name must not be empty")
- }
-
- if exportCount := uint32(len(nameToHostFunc)); exportCount > 0 {
- m.ExportSection = make([]Export, 0, exportCount)
- m.Exports = make(map[string]*Export, exportCount)
- if err = addFuncs(m, exportNames, nameToHostFunc, enabledFeatures); err != nil {
- return
- }
- }
-
- m.IsHostModule = true
- // Uses the address of *wasm.Module as the module ID so that host functions can have each state per compilation.
- // Downside of this is that compilation cache on host functions (trampoline codes for Go functions and
- // Wasm codes for Wasm-implemented host functions) are not available and compiles each time. On the other hand,
- // compilation of host modules is not costly as it's merely small trampolines vs the real-world native Wasm binary.
- // TODO: refactor engines so that we can properly cache compiled machine codes for host modules.
- m.AssignModuleID([]byte(fmt.Sprintf("@@@@@@@@%p", m)), // @@@@@@@@ = any 8 bytes different from Wasm header.
- nil, false)
- return
-}
-
-func addFuncs(
- m *Module,
- exportNames []string,
- nameToHostFunc map[string]*HostFunc,
- enabledFeatures api.CoreFeatures,
-) (err error) {
- if m.NameSection == nil {
- m.NameSection = &NameSection{}
- }
- moduleName := m.NameSection.ModuleName
-
- for _, k := range exportNames {
- hf := nameToHostFunc[k]
- if hf.Name == "" {
- hf.Name = k // default name to export name
- }
- switch hf.Code.GoFunc.(type) {
- case api.GoModuleFunction, api.GoFunction:
- continue // already parsed
- }
-
- // Resolve the code using reflection
- hf.ParamTypes, hf.ResultTypes, hf.Code, err = parseGoReflectFunc(hf.Code.GoFunc)
- if err != nil {
- return fmt.Errorf("func[%s.%s] %w", moduleName, k, err)
- }
-
- // Assign names to the function, if they exist.
- params := hf.ParamTypes
- if paramNames := hf.ParamNames; paramNames != nil {
- if paramNamesLen := len(paramNames); paramNamesLen != len(params) {
- return fmt.Errorf("func[%s.%s] has %d params, but %d params names", moduleName, k, paramNamesLen, len(params))
- }
- }
-
- results := hf.ResultTypes
- if resultNames := hf.ResultNames; resultNames != nil {
- if resultNamesLen := len(resultNames); resultNamesLen != len(results) {
- return fmt.Errorf("func[%s.%s] has %d results, but %d results names", moduleName, k, resultNamesLen, len(results))
- }
- }
- }
-
- funcCount := uint32(len(exportNames))
- m.NameSection.FunctionNames = make([]NameAssoc, 0, funcCount)
- m.FunctionSection = make([]Index, 0, funcCount)
- m.CodeSection = make([]Code, 0, funcCount)
-
- idx := Index(0)
- for _, name := range exportNames {
- hf := nameToHostFunc[name]
- debugName := wasmdebug.FuncName(moduleName, name, idx)
- typeIdx, typeErr := m.maybeAddType(hf.ParamTypes, hf.ResultTypes, enabledFeatures)
- if typeErr != nil {
- return fmt.Errorf("func[%s] %v", debugName, typeErr)
- }
- m.FunctionSection = append(m.FunctionSection, typeIdx)
- m.CodeSection = append(m.CodeSection, hf.Code)
-
- export := hf.ExportName
- m.ExportSection = append(m.ExportSection, Export{Type: ExternTypeFunc, Name: export, Index: idx})
- m.Exports[export] = &m.ExportSection[len(m.ExportSection)-1]
- m.NameSection.FunctionNames = append(m.NameSection.FunctionNames, NameAssoc{Index: idx, Name: hf.Name})
-
- if len(hf.ParamNames) > 0 {
- localNames := NameMapAssoc{Index: idx}
- for i, n := range hf.ParamNames {
- localNames.NameMap = append(localNames.NameMap, NameAssoc{Index: Index(i), Name: n})
- }
- m.NameSection.LocalNames = append(m.NameSection.LocalNames, localNames)
- }
- if len(hf.ResultNames) > 0 {
- resultNames := NameMapAssoc{Index: idx}
- for i, n := range hf.ResultNames {
- resultNames.NameMap = append(resultNames.NameMap, NameAssoc{Index: Index(i), Name: n})
- }
- m.NameSection.ResultNames = append(m.NameSection.ResultNames, resultNames)
- }
- idx++
- }
- return nil
-}
-
-func (m *Module) maybeAddType(params, results []ValueType, enabledFeatures api.CoreFeatures) (Index, error) {
- if len(results) > 1 {
- // Guard >1.0 feature multi-value
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
- return 0, fmt.Errorf("multiple result types invalid as %v", err)
- }
- }
- for i := range m.TypeSection {
- t := &m.TypeSection[i]
- if t.EqualsSignature(params, results) {
- return Index(i), nil
- }
- }
-
- result := m.SectionElementCount(SectionIDType)
- m.TypeSection = append(m.TypeSection, FunctionType{Params: params, Results: results})
- return result, nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go
deleted file mode 100644
index 67f196b8b..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/instruction.go
+++ /dev/null
@@ -1,1866 +0,0 @@
-package wasm
-
-// Opcode is the binary Opcode of an instruction. See also InstructionName
-type Opcode = byte
-
-const (
- // OpcodeUnreachable causes an unconditional trap.
- OpcodeUnreachable Opcode = 0x00
- // OpcodeNop does nothing
- OpcodeNop Opcode = 0x01
- // OpcodeBlock brackets a sequence of instructions. A branch instruction on an if label breaks out to after its
- // OpcodeEnd.
- OpcodeBlock Opcode = 0x02
- // OpcodeLoop brackets a sequence of instructions. A branch instruction on a loop label will jump back to the
- // beginning of its block.
- OpcodeLoop Opcode = 0x03
- // OpcodeIf brackets a sequence of instructions. When the top of the stack evaluates to 1, the block is executed.
- // Zero jumps to the optional OpcodeElse. A branch instruction on an if label breaks out to after its OpcodeEnd.
- OpcodeIf Opcode = 0x04
- // OpcodeElse brackets a sequence of instructions enclosed by an OpcodeIf. A branch instruction on a then label
- // breaks out to after the OpcodeEnd on the enclosing OpcodeIf.
- OpcodeElse Opcode = 0x05
- // OpcodeEnd terminates a control instruction OpcodeBlock, OpcodeLoop or OpcodeIf.
- OpcodeEnd Opcode = 0x0b
-
- // OpcodeBr is a stack-polymorphic opcode that performs an unconditional branch. How the stack is modified depends
- // on whether the "br" is enclosed by a loop, and if CoreFeatureMultiValue is enabled.
- //
- // Here are the rules in pseudocode about how the stack is modified based on the "br" operand L (label):
- // if L is loop: append(L.originalStackWithoutInputs, N-values popped from the stack) where N == L.inputs
- // else: append(L.originalStackWithoutInputs, N-values popped from the stack) where N == L.results
- //
- // In WebAssembly 1.0 (20191205), N can be zero or one. When CoreFeatureMultiValue is enabled, N can be more than one,
- // depending on the type use of the label L.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefsyntax-instr-controlmathsfbrl
- OpcodeBr Opcode = 0x0c
-
- OpcodeBrIf Opcode = 0x0d
- OpcodeBrTable Opcode = 0x0e
- OpcodeReturn Opcode = 0x0f
- OpcodeCall Opcode = 0x10
- OpcodeCallIndirect Opcode = 0x11
-
- // parametric instructions
-
- OpcodeDrop Opcode = 0x1a
- OpcodeSelect Opcode = 0x1b
- OpcodeTypedSelect Opcode = 0x1c
-
- // variable instructions
-
- OpcodeLocalGet Opcode = 0x20
- OpcodeLocalSet Opcode = 0x21
- OpcodeLocalTee Opcode = 0x22
- OpcodeGlobalGet Opcode = 0x23
- OpcodeGlobalSet Opcode = 0x24
-
- // Below are toggled with CoreFeatureReferenceTypes
-
- OpcodeTableGet Opcode = 0x25
- OpcodeTableSet Opcode = 0x26
-
- // memory instructions
-
- OpcodeI32Load Opcode = 0x28
- OpcodeI64Load Opcode = 0x29
- OpcodeF32Load Opcode = 0x2a
- OpcodeF64Load Opcode = 0x2b
- OpcodeI32Load8S Opcode = 0x2c
- OpcodeI32Load8U Opcode = 0x2d
- OpcodeI32Load16S Opcode = 0x2e
- OpcodeI32Load16U Opcode = 0x2f
- OpcodeI64Load8S Opcode = 0x30
- OpcodeI64Load8U Opcode = 0x31
- OpcodeI64Load16S Opcode = 0x32
- OpcodeI64Load16U Opcode = 0x33
- OpcodeI64Load32S Opcode = 0x34
- OpcodeI64Load32U Opcode = 0x35
- OpcodeI32Store Opcode = 0x36
- OpcodeI64Store Opcode = 0x37
- OpcodeF32Store Opcode = 0x38
- OpcodeF64Store Opcode = 0x39
- OpcodeI32Store8 Opcode = 0x3a
- OpcodeI32Store16 Opcode = 0x3b
- OpcodeI64Store8 Opcode = 0x3c
- OpcodeI64Store16 Opcode = 0x3d
- OpcodeI64Store32 Opcode = 0x3e
- OpcodeMemorySize Opcode = 0x3f
- OpcodeMemoryGrow Opcode = 0x40
-
- // const instructions
-
- OpcodeI32Const Opcode = 0x41
- OpcodeI64Const Opcode = 0x42
- OpcodeF32Const Opcode = 0x43
- OpcodeF64Const Opcode = 0x44
-
- // numeric instructions
-
- OpcodeI32Eqz Opcode = 0x45
- OpcodeI32Eq Opcode = 0x46
- OpcodeI32Ne Opcode = 0x47
- OpcodeI32LtS Opcode = 0x48
- OpcodeI32LtU Opcode = 0x49
- OpcodeI32GtS Opcode = 0x4a
- OpcodeI32GtU Opcode = 0x4b
- OpcodeI32LeS Opcode = 0x4c
- OpcodeI32LeU Opcode = 0x4d
- OpcodeI32GeS Opcode = 0x4e
- OpcodeI32GeU Opcode = 0x4f
-
- OpcodeI64Eqz Opcode = 0x50
- OpcodeI64Eq Opcode = 0x51
- OpcodeI64Ne Opcode = 0x52
- OpcodeI64LtS Opcode = 0x53
- OpcodeI64LtU Opcode = 0x54
- OpcodeI64GtS Opcode = 0x55
- OpcodeI64GtU Opcode = 0x56
- OpcodeI64LeS Opcode = 0x57
- OpcodeI64LeU Opcode = 0x58
- OpcodeI64GeS Opcode = 0x59
- OpcodeI64GeU Opcode = 0x5a
-
- OpcodeF32Eq Opcode = 0x5b
- OpcodeF32Ne Opcode = 0x5c
- OpcodeF32Lt Opcode = 0x5d
- OpcodeF32Gt Opcode = 0x5e
- OpcodeF32Le Opcode = 0x5f
- OpcodeF32Ge Opcode = 0x60
-
- OpcodeF64Eq Opcode = 0x61
- OpcodeF64Ne Opcode = 0x62
- OpcodeF64Lt Opcode = 0x63
- OpcodeF64Gt Opcode = 0x64
- OpcodeF64Le Opcode = 0x65
- OpcodeF64Ge Opcode = 0x66
-
- OpcodeI32Clz Opcode = 0x67
- OpcodeI32Ctz Opcode = 0x68
- OpcodeI32Popcnt Opcode = 0x69
- OpcodeI32Add Opcode = 0x6a
- OpcodeI32Sub Opcode = 0x6b
- OpcodeI32Mul Opcode = 0x6c
- OpcodeI32DivS Opcode = 0x6d
- OpcodeI32DivU Opcode = 0x6e
- OpcodeI32RemS Opcode = 0x6f
- OpcodeI32RemU Opcode = 0x70
- OpcodeI32And Opcode = 0x71
- OpcodeI32Or Opcode = 0x72
- OpcodeI32Xor Opcode = 0x73
- OpcodeI32Shl Opcode = 0x74
- OpcodeI32ShrS Opcode = 0x75
- OpcodeI32ShrU Opcode = 0x76
- OpcodeI32Rotl Opcode = 0x77
- OpcodeI32Rotr Opcode = 0x78
-
- OpcodeI64Clz Opcode = 0x79
- OpcodeI64Ctz Opcode = 0x7a
- OpcodeI64Popcnt Opcode = 0x7b
- OpcodeI64Add Opcode = 0x7c
- OpcodeI64Sub Opcode = 0x7d
- OpcodeI64Mul Opcode = 0x7e
- OpcodeI64DivS Opcode = 0x7f
- OpcodeI64DivU Opcode = 0x80
- OpcodeI64RemS Opcode = 0x81
- OpcodeI64RemU Opcode = 0x82
- OpcodeI64And Opcode = 0x83
- OpcodeI64Or Opcode = 0x84
- OpcodeI64Xor Opcode = 0x85
- OpcodeI64Shl Opcode = 0x86
- OpcodeI64ShrS Opcode = 0x87
- OpcodeI64ShrU Opcode = 0x88
- OpcodeI64Rotl Opcode = 0x89
- OpcodeI64Rotr Opcode = 0x8a
-
- OpcodeF32Abs Opcode = 0x8b
- OpcodeF32Neg Opcode = 0x8c
- OpcodeF32Ceil Opcode = 0x8d
- OpcodeF32Floor Opcode = 0x8e
- OpcodeF32Trunc Opcode = 0x8f
- OpcodeF32Nearest Opcode = 0x90
- OpcodeF32Sqrt Opcode = 0x91
- OpcodeF32Add Opcode = 0x92
- OpcodeF32Sub Opcode = 0x93
- OpcodeF32Mul Opcode = 0x94
- OpcodeF32Div Opcode = 0x95
- OpcodeF32Min Opcode = 0x96
- OpcodeF32Max Opcode = 0x97
- OpcodeF32Copysign Opcode = 0x98
-
- OpcodeF64Abs Opcode = 0x99
- OpcodeF64Neg Opcode = 0x9a
- OpcodeF64Ceil Opcode = 0x9b
- OpcodeF64Floor Opcode = 0x9c
- OpcodeF64Trunc Opcode = 0x9d
- OpcodeF64Nearest Opcode = 0x9e
- OpcodeF64Sqrt Opcode = 0x9f
- OpcodeF64Add Opcode = 0xa0
- OpcodeF64Sub Opcode = 0xa1
- OpcodeF64Mul Opcode = 0xa2
- OpcodeF64Div Opcode = 0xa3
- OpcodeF64Min Opcode = 0xa4
- OpcodeF64Max Opcode = 0xa5
- OpcodeF64Copysign Opcode = 0xa6
-
- OpcodeI32WrapI64 Opcode = 0xa7
- OpcodeI32TruncF32S Opcode = 0xa8
- OpcodeI32TruncF32U Opcode = 0xa9
- OpcodeI32TruncF64S Opcode = 0xaa
- OpcodeI32TruncF64U Opcode = 0xab
-
- OpcodeI64ExtendI32S Opcode = 0xac
- OpcodeI64ExtendI32U Opcode = 0xad
- OpcodeI64TruncF32S Opcode = 0xae
- OpcodeI64TruncF32U Opcode = 0xaf
- OpcodeI64TruncF64S Opcode = 0xb0
- OpcodeI64TruncF64U Opcode = 0xb1
-
- OpcodeF32ConvertI32S Opcode = 0xb2
- OpcodeF32ConvertI32U Opcode = 0xb3
- OpcodeF32ConvertI64S Opcode = 0xb4
- OpcodeF32ConvertI64U Opcode = 0xb5
- OpcodeF32DemoteF64 Opcode = 0xb6
-
- OpcodeF64ConvertI32S Opcode = 0xb7
- OpcodeF64ConvertI32U Opcode = 0xb8
- OpcodeF64ConvertI64S Opcode = 0xb9
- OpcodeF64ConvertI64U Opcode = 0xba
- OpcodeF64PromoteF32 Opcode = 0xbb
-
- OpcodeI32ReinterpretF32 Opcode = 0xbc
- OpcodeI64ReinterpretF64 Opcode = 0xbd
- OpcodeF32ReinterpretI32 Opcode = 0xbe
- OpcodeF64ReinterpretI64 Opcode = 0xbf
-
- // OpcodeRefNull pushes a null reference value whose type is specified by immediate to this opcode.
- // This is defined in the reference-types proposal, but necessary for CoreFeatureBulkMemoryOperations as well.
- //
- // Currently only supported in the constant expression in element segments.
- OpcodeRefNull = 0xd0
- // OpcodeRefIsNull pops a reference value, and pushes 1 if it is null, 0 otherwise.
- // This is defined in the reference-types proposal, but necessary for CoreFeatureBulkMemoryOperations as well.
- //
- // Currently not supported.
- OpcodeRefIsNull = 0xd1
- // OpcodeRefFunc pushes a funcref value whose index equals the immediate to this opcode.
- // This is defined in the reference-types proposal, but necessary for CoreFeatureBulkMemoryOperations as well.
- //
- // Currently, this is only supported in the constant expression in element segments.
- OpcodeRefFunc = 0xd2
-
- // Below are toggled with CoreFeatureSignExtensionOps
-
- // OpcodeI32Extend8S extends a signed 8-bit integer to a 32-bit integer.
- // Note: This is dependent on the flag CoreFeatureSignExtensionOps
- OpcodeI32Extend8S Opcode = 0xc0
-
- // OpcodeI32Extend16S extends a signed 16-bit integer to a 32-bit integer.
- // Note: This is dependent on the flag CoreFeatureSignExtensionOps
- OpcodeI32Extend16S Opcode = 0xc1
-
- // OpcodeI64Extend8S extends a signed 8-bit integer to a 64-bit integer.
- // Note: This is dependent on the flag CoreFeatureSignExtensionOps
- OpcodeI64Extend8S Opcode = 0xc2
-
- // OpcodeI64Extend16S extends a signed 16-bit integer to a 64-bit integer.
- // Note: This is dependent on the flag CoreFeatureSignExtensionOps
- OpcodeI64Extend16S Opcode = 0xc3
-
- // OpcodeI64Extend32S extends a signed 32-bit integer to a 64-bit integer.
- // Note: This is dependent on the flag CoreFeatureSignExtensionOps
- OpcodeI64Extend32S Opcode = 0xc4
-
- // OpcodeMiscPrefix is the prefix of various multi-byte opcodes.
- // Introduced in CoreFeatureNonTrappingFloatToIntConversion, but used in other
- // features, such as CoreFeatureBulkMemoryOperations.
- OpcodeMiscPrefix Opcode = 0xfc
-
- // OpcodeVecPrefix is the prefix of all vector isntructions introduced in
- // CoreFeatureSIMD.
- OpcodeVecPrefix Opcode = 0xfd
-
- // OpcodeAtomicPrefix is the prefix of all atomic instructions introduced in
- // CoreFeatureThreads.
- OpcodeAtomicPrefix Opcode = 0xfe
-)
-
-// OpcodeMisc represents opcodes of the miscellaneous operations.
-// Such an operations has multi-byte encoding which is prefixed by OpcodeMiscPrefix.
-type OpcodeMisc = byte
-
-const (
- // Below are toggled with CoreFeatureNonTrappingFloatToIntConversion.
- // https://github.com/WebAssembly/spec/blob/ce4b6c4d47eb06098cc7ab2e81f24748da822f20/proposals/nontrapping-float-to-int-conversion/Overview.md
-
- OpcodeMiscI32TruncSatF32S OpcodeMisc = 0x00
- OpcodeMiscI32TruncSatF32U OpcodeMisc = 0x01
- OpcodeMiscI32TruncSatF64S OpcodeMisc = 0x02
- OpcodeMiscI32TruncSatF64U OpcodeMisc = 0x03
- OpcodeMiscI64TruncSatF32S OpcodeMisc = 0x04
- OpcodeMiscI64TruncSatF32U OpcodeMisc = 0x05
- OpcodeMiscI64TruncSatF64S OpcodeMisc = 0x06
- OpcodeMiscI64TruncSatF64U OpcodeMisc = 0x07
-
- // Below are toggled with CoreFeatureBulkMemoryOperations.
- // Opcodes are those new in document/core/appendix/index-instructions.rst (the commit that merged the feature).
- // See https://github.com/WebAssembly/spec/commit/7fa2f20a6df4cf1c114582c8cb60f5bfcdbf1be1
- // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions
-
- OpcodeMiscMemoryInit OpcodeMisc = 0x08
- OpcodeMiscDataDrop OpcodeMisc = 0x09
- OpcodeMiscMemoryCopy OpcodeMisc = 0x0a
- OpcodeMiscMemoryFill OpcodeMisc = 0x0b
- OpcodeMiscTableInit OpcodeMisc = 0x0c
- OpcodeMiscElemDrop OpcodeMisc = 0x0d
- OpcodeMiscTableCopy OpcodeMisc = 0x0e
-
- // Below are toggled with CoreFeatureReferenceTypes
-
- OpcodeMiscTableGrow OpcodeMisc = 0x0f
- OpcodeMiscTableSize OpcodeMisc = 0x10
- OpcodeMiscTableFill OpcodeMisc = 0x11
-)
-
-// OpcodeVec represents an opcode of a vector instructions which has
-// multi-byte encoding and is prefixed by OpcodeMiscPrefix.
-//
-// These opcodes are toggled with CoreFeatureSIMD.
-type OpcodeVec = byte
-
-const (
- // Loads and stores.
-
- OpcodeVecV128Load OpcodeVec = 0x00
- OpcodeVecV128Load8x8s OpcodeVec = 0x01
- OpcodeVecV128Load8x8u OpcodeVec = 0x02
- OpcodeVecV128Load16x4s OpcodeVec = 0x03
- OpcodeVecV128Load16x4u OpcodeVec = 0x04
- OpcodeVecV128Load32x2s OpcodeVec = 0x05
- OpcodeVecV128Load32x2u OpcodeVec = 0x06
- OpcodeVecV128Load8Splat OpcodeVec = 0x07
- OpcodeVecV128Load16Splat OpcodeVec = 0x08
- OpcodeVecV128Load32Splat OpcodeVec = 0x09
- OpcodeVecV128Load64Splat OpcodeVec = 0x0a
-
- OpcodeVecV128Load32zero OpcodeVec = 0x5c
- OpcodeVecV128Load64zero OpcodeVec = 0x5d
-
- OpcodeVecV128Store OpcodeVec = 0x0b
- OpcodeVecV128Load8Lane OpcodeVec = 0x54
- OpcodeVecV128Load16Lane OpcodeVec = 0x55
- OpcodeVecV128Load32Lane OpcodeVec = 0x56
- OpcodeVecV128Load64Lane OpcodeVec = 0x57
- OpcodeVecV128Store8Lane OpcodeVec = 0x58
- OpcodeVecV128Store16Lane OpcodeVec = 0x59
- OpcodeVecV128Store32Lane OpcodeVec = 0x5a
- OpcodeVecV128Store64Lane OpcodeVec = 0x5b
-
- // OpcodeVecV128Const is the vector const instruction.
- OpcodeVecV128Const OpcodeVec = 0x0c
-
- // OpcodeVecV128i8x16Shuffle is the vector shuffle instruction.
- OpcodeVecV128i8x16Shuffle OpcodeVec = 0x0d
-
- // Extrac and replaces.
-
- OpcodeVecI8x16ExtractLaneS OpcodeVec = 0x15
- OpcodeVecI8x16ExtractLaneU OpcodeVec = 0x16
- OpcodeVecI8x16ReplaceLane OpcodeVec = 0x17
- OpcodeVecI16x8ExtractLaneS OpcodeVec = 0x18
- OpcodeVecI16x8ExtractLaneU OpcodeVec = 0x19
- OpcodeVecI16x8ReplaceLane OpcodeVec = 0x1a
- OpcodeVecI32x4ExtractLane OpcodeVec = 0x1b
- OpcodeVecI32x4ReplaceLane OpcodeVec = 0x1c
- OpcodeVecI64x2ExtractLane OpcodeVec = 0x1d
- OpcodeVecI64x2ReplaceLane OpcodeVec = 0x1e
- OpcodeVecF32x4ExtractLane OpcodeVec = 0x1f
- OpcodeVecF32x4ReplaceLane OpcodeVec = 0x20
- OpcodeVecF64x2ExtractLane OpcodeVec = 0x21
- OpcodeVecF64x2ReplaceLane OpcodeVec = 0x22
-
- // Splat and swizzle.
-
- OpcodeVecI8x16Swizzle OpcodeVec = 0x0e
- OpcodeVecI8x16Splat OpcodeVec = 0x0f
- OpcodeVecI16x8Splat OpcodeVec = 0x10
- OpcodeVecI32x4Splat OpcodeVec = 0x11
- OpcodeVecI64x2Splat OpcodeVec = 0x12
- OpcodeVecF32x4Splat OpcodeVec = 0x13
- OpcodeVecF64x2Splat OpcodeVec = 0x14
-
- // i8 comparisons.
-
- OpcodeVecI8x16Eq OpcodeVec = 0x23
- OpcodeVecI8x16Ne OpcodeVec = 0x24
- OpcodeVecI8x16LtS OpcodeVec = 0x25
- OpcodeVecI8x16LtU OpcodeVec = 0x26
- OpcodeVecI8x16GtS OpcodeVec = 0x27
- OpcodeVecI8x16GtU OpcodeVec = 0x28
- OpcodeVecI8x16LeS OpcodeVec = 0x29
- OpcodeVecI8x16LeU OpcodeVec = 0x2a
- OpcodeVecI8x16GeS OpcodeVec = 0x2b
- OpcodeVecI8x16GeU OpcodeVec = 0x2c
-
- // i16 comparisons.
-
- OpcodeVecI16x8Eq OpcodeVec = 0x2d
- OpcodeVecI16x8Ne OpcodeVec = 0x2e
- OpcodeVecI16x8LtS OpcodeVec = 0x2f
- OpcodeVecI16x8LtU OpcodeVec = 0x30
- OpcodeVecI16x8GtS OpcodeVec = 0x31
- OpcodeVecI16x8GtU OpcodeVec = 0x32
- OpcodeVecI16x8LeS OpcodeVec = 0x33
- OpcodeVecI16x8LeU OpcodeVec = 0x34
- OpcodeVecI16x8GeS OpcodeVec = 0x35
- OpcodeVecI16x8GeU OpcodeVec = 0x36
-
- // i32 comparisons.
-
- OpcodeVecI32x4Eq OpcodeVec = 0x37
- OpcodeVecI32x4Ne OpcodeVec = 0x38
- OpcodeVecI32x4LtS OpcodeVec = 0x39
- OpcodeVecI32x4LtU OpcodeVec = 0x3a
- OpcodeVecI32x4GtS OpcodeVec = 0x3b
- OpcodeVecI32x4GtU OpcodeVec = 0x3c
- OpcodeVecI32x4LeS OpcodeVec = 0x3d
- OpcodeVecI32x4LeU OpcodeVec = 0x3e
- OpcodeVecI32x4GeS OpcodeVec = 0x3f
- OpcodeVecI32x4GeU OpcodeVec = 0x40
-
- // i64 comparisons.
-
- OpcodeVecI64x2Eq OpcodeVec = 0xd6
- OpcodeVecI64x2Ne OpcodeVec = 0xd7
- OpcodeVecI64x2LtS OpcodeVec = 0xd8
- OpcodeVecI64x2GtS OpcodeVec = 0xd9
- OpcodeVecI64x2LeS OpcodeVec = 0xda
- OpcodeVecI64x2GeS OpcodeVec = 0xdb
-
- // f32 comparisons.
-
- OpcodeVecF32x4Eq OpcodeVec = 0x41
- OpcodeVecF32x4Ne OpcodeVec = 0x42
- OpcodeVecF32x4Lt OpcodeVec = 0x43
- OpcodeVecF32x4Gt OpcodeVec = 0x44
- OpcodeVecF32x4Le OpcodeVec = 0x45
- OpcodeVecF32x4Ge OpcodeVec = 0x46
-
- // f64 comparisons.
-
- OpcodeVecF64x2Eq OpcodeVec = 0x47
- OpcodeVecF64x2Ne OpcodeVec = 0x48
- OpcodeVecF64x2Lt OpcodeVec = 0x49
- OpcodeVecF64x2Gt OpcodeVec = 0x4a
- OpcodeVecF64x2Le OpcodeVec = 0x4b
- OpcodeVecF64x2Ge OpcodeVec = 0x4c
-
- // v128 logical instructions.
-
- OpcodeVecV128Not OpcodeVec = 0x4d
- OpcodeVecV128And OpcodeVec = 0x4e
- OpcodeVecV128AndNot OpcodeVec = 0x4f
- OpcodeVecV128Or OpcodeVec = 0x50
- OpcodeVecV128Xor OpcodeVec = 0x51
- OpcodeVecV128Bitselect OpcodeVec = 0x52
- OpcodeVecV128AnyTrue OpcodeVec = 0x53
-
- // i8 misc.
-
- OpcodeVecI8x16Abs OpcodeVec = 0x60
- OpcodeVecI8x16Neg OpcodeVec = 0x61
- OpcodeVecI8x16Popcnt OpcodeVec = 0x62
- OpcodeVecI8x16AllTrue OpcodeVec = 0x63
- OpcodeVecI8x16BitMask OpcodeVec = 0x64
- OpcodeVecI8x16NarrowI16x8S OpcodeVec = 0x65
- OpcodeVecI8x16NarrowI16x8U OpcodeVec = 0x66
-
- OpcodeVecI8x16Shl OpcodeVec = 0x6b
- OpcodeVecI8x16ShrS OpcodeVec = 0x6c
- OpcodeVecI8x16ShrU OpcodeVec = 0x6d
- OpcodeVecI8x16Add OpcodeVec = 0x6e
- OpcodeVecI8x16AddSatS OpcodeVec = 0x6f
-
- OpcodeVecI8x16AddSatU OpcodeVec = 0x70
- OpcodeVecI8x16Sub OpcodeVec = 0x71
- OpcodeVecI8x16SubSatS OpcodeVec = 0x72
- OpcodeVecI8x16SubSatU OpcodeVec = 0x73
- OpcodeVecI8x16MinS OpcodeVec = 0x76
- OpcodeVecI8x16MinU OpcodeVec = 0x77
- OpcodeVecI8x16MaxS OpcodeVec = 0x78
- OpcodeVecI8x16MaxU OpcodeVec = 0x79
- OpcodeVecI8x16AvgrU OpcodeVec = 0x7b
-
- // i16 misc.
-
- OpcodeVecI16x8ExtaddPairwiseI8x16S OpcodeVec = 0x7c
- OpcodeVecI16x8ExtaddPairwiseI8x16U OpcodeVec = 0x7d
- OpcodeVecI16x8Abs OpcodeVec = 0x80
- OpcodeVecI16x8Neg OpcodeVec = 0x81
- OpcodeVecI16x8Q15mulrSatS OpcodeVec = 0x82
- OpcodeVecI16x8AllTrue OpcodeVec = 0x83
- OpcodeVecI16x8BitMask OpcodeVec = 0x84
- OpcodeVecI16x8NarrowI32x4S OpcodeVec = 0x85
- OpcodeVecI16x8NarrowI32x4U OpcodeVec = 0x86
- OpcodeVecI16x8ExtendLowI8x16S OpcodeVec = 0x87
- OpcodeVecI16x8ExtendHighI8x16S OpcodeVec = 0x88
- OpcodeVecI16x8ExtendLowI8x16U OpcodeVec = 0x89
- OpcodeVecI16x8ExtendHighI8x16U OpcodeVec = 0x8a
- OpcodeVecI16x8Shl OpcodeVec = 0x8b
- OpcodeVecI16x8ShrS OpcodeVec = 0x8c
- OpcodeVecI16x8ShrU OpcodeVec = 0x8d
- OpcodeVecI16x8Add OpcodeVec = 0x8e
- OpcodeVecI16x8AddSatS OpcodeVec = 0x8f
- OpcodeVecI16x8AddSatU OpcodeVec = 0x90
- OpcodeVecI16x8Sub OpcodeVec = 0x91
- OpcodeVecI16x8SubSatS OpcodeVec = 0x92
- OpcodeVecI16x8SubSatU OpcodeVec = 0x93
- OpcodeVecI16x8Mul OpcodeVec = 0x95
- OpcodeVecI16x8MinS OpcodeVec = 0x96
- OpcodeVecI16x8MinU OpcodeVec = 0x97
- OpcodeVecI16x8MaxS OpcodeVec = 0x98
- OpcodeVecI16x8MaxU OpcodeVec = 0x99
- OpcodeVecI16x8AvgrU OpcodeVec = 0x9b
- OpcodeVecI16x8ExtMulLowI8x16S OpcodeVec = 0x9c
- OpcodeVecI16x8ExtMulHighI8x16S OpcodeVec = 0x9d
- OpcodeVecI16x8ExtMulLowI8x16U OpcodeVec = 0x9e
- OpcodeVecI16x8ExtMulHighI8x16U OpcodeVec = 0x9f
-
- // i32 misc.
-
- OpcodeVecI32x4ExtaddPairwiseI16x8S OpcodeVec = 0x7e
- OpcodeVecI32x4ExtaddPairwiseI16x8U OpcodeVec = 0x7f
- OpcodeVecI32x4Abs OpcodeVec = 0xa0
- OpcodeVecI32x4Neg OpcodeVec = 0xa1
- OpcodeVecI32x4AllTrue OpcodeVec = 0xa3
- OpcodeVecI32x4BitMask OpcodeVec = 0xa4
- OpcodeVecI32x4ExtendLowI16x8S OpcodeVec = 0xa7
- OpcodeVecI32x4ExtendHighI16x8S OpcodeVec = 0xa8
- OpcodeVecI32x4ExtendLowI16x8U OpcodeVec = 0xa9
- OpcodeVecI32x4ExtendHighI16x8U OpcodeVec = 0xaa
- OpcodeVecI32x4Shl OpcodeVec = 0xab
- OpcodeVecI32x4ShrS OpcodeVec = 0xac
- OpcodeVecI32x4ShrU OpcodeVec = 0xad
- OpcodeVecI32x4Add OpcodeVec = 0xae
- OpcodeVecI32x4Sub OpcodeVec = 0xb1
- OpcodeVecI32x4Mul OpcodeVec = 0xb5
- OpcodeVecI32x4MinS OpcodeVec = 0xb6
- OpcodeVecI32x4MinU OpcodeVec = 0xb7
- OpcodeVecI32x4MaxS OpcodeVec = 0xb8
- OpcodeVecI32x4MaxU OpcodeVec = 0xb9
- OpcodeVecI32x4DotI16x8S OpcodeVec = 0xba
- OpcodeVecI32x4ExtMulLowI16x8S OpcodeVec = 0xbc
- OpcodeVecI32x4ExtMulHighI16x8S OpcodeVec = 0xbd
- OpcodeVecI32x4ExtMulLowI16x8U OpcodeVec = 0xbe
- OpcodeVecI32x4ExtMulHighI16x8U OpcodeVec = 0xbf
-
- // i64 misc.
-
- OpcodeVecI64x2Abs OpcodeVec = 0xc0
- OpcodeVecI64x2Neg OpcodeVec = 0xc1
- OpcodeVecI64x2AllTrue OpcodeVec = 0xc3
- OpcodeVecI64x2BitMask OpcodeVec = 0xc4
- OpcodeVecI64x2ExtendLowI32x4S OpcodeVec = 0xc7
- OpcodeVecI64x2ExtendHighI32x4S OpcodeVec = 0xc8
- OpcodeVecI64x2ExtendLowI32x4U OpcodeVec = 0xc9
- OpcodeVecI64x2ExtendHighI32x4U OpcodeVec = 0xca
- OpcodeVecI64x2Shl OpcodeVec = 0xcb
- OpcodeVecI64x2ShrS OpcodeVec = 0xcc
- OpcodeVecI64x2ShrU OpcodeVec = 0xcd
- OpcodeVecI64x2Add OpcodeVec = 0xce
- OpcodeVecI64x2Sub OpcodeVec = 0xd1
- OpcodeVecI64x2Mul OpcodeVec = 0xd5
- OpcodeVecI64x2ExtMulLowI32x4S OpcodeVec = 0xdc
- OpcodeVecI64x2ExtMulHighI32x4S OpcodeVec = 0xdd
- OpcodeVecI64x2ExtMulLowI32x4U OpcodeVec = 0xde
- OpcodeVecI64x2ExtMulHighI32x4U OpcodeVec = 0xdf
-
- // f32 misc.
-
- OpcodeVecF32x4Ceil OpcodeVec = 0x67
- OpcodeVecF32x4Floor OpcodeVec = 0x68
- OpcodeVecF32x4Trunc OpcodeVec = 0x69
- OpcodeVecF32x4Nearest OpcodeVec = 0x6a
- OpcodeVecF32x4Abs OpcodeVec = 0xe0
- OpcodeVecF32x4Neg OpcodeVec = 0xe1
- OpcodeVecF32x4Sqrt OpcodeVec = 0xe3
- OpcodeVecF32x4Add OpcodeVec = 0xe4
- OpcodeVecF32x4Sub OpcodeVec = 0xe5
- OpcodeVecF32x4Mul OpcodeVec = 0xe6
- OpcodeVecF32x4Div OpcodeVec = 0xe7
- OpcodeVecF32x4Min OpcodeVec = 0xe8
- OpcodeVecF32x4Max OpcodeVec = 0xe9
- OpcodeVecF32x4Pmin OpcodeVec = 0xea
- OpcodeVecF32x4Pmax OpcodeVec = 0xeb
-
- // f64 misc.
-
- OpcodeVecF64x2Ceil OpcodeVec = 0x74
- OpcodeVecF64x2Floor OpcodeVec = 0x75
- OpcodeVecF64x2Trunc OpcodeVec = 0x7a
- OpcodeVecF64x2Nearest OpcodeVec = 0x94
- OpcodeVecF64x2Abs OpcodeVec = 0xec
- OpcodeVecF64x2Neg OpcodeVec = 0xed
- OpcodeVecF64x2Sqrt OpcodeVec = 0xef
- OpcodeVecF64x2Add OpcodeVec = 0xf0
- OpcodeVecF64x2Sub OpcodeVec = 0xf1
- OpcodeVecF64x2Mul OpcodeVec = 0xf2
- OpcodeVecF64x2Div OpcodeVec = 0xf3
- OpcodeVecF64x2Min OpcodeVec = 0xf4
- OpcodeVecF64x2Max OpcodeVec = 0xf5
- OpcodeVecF64x2Pmin OpcodeVec = 0xf6
- OpcodeVecF64x2Pmax OpcodeVec = 0xf7
-
- // conversions.
-
- OpcodeVecI32x4TruncSatF32x4S OpcodeVec = 0xf8
- OpcodeVecI32x4TruncSatF32x4U OpcodeVec = 0xf9
- OpcodeVecF32x4ConvertI32x4S OpcodeVec = 0xfa
- OpcodeVecF32x4ConvertI32x4U OpcodeVec = 0xfb
- OpcodeVecI32x4TruncSatF64x2SZero OpcodeVec = 0xfc
- OpcodeVecI32x4TruncSatF64x2UZero OpcodeVec = 0xfd
- OpcodeVecF64x2ConvertLowI32x4S OpcodeVec = 0xfe
- OpcodeVecF64x2ConvertLowI32x4U OpcodeVec = 0xff
- OpcodeVecF32x4DemoteF64x2Zero OpcodeVec = 0x5e
- OpcodeVecF64x2PromoteLowF32x4Zero OpcodeVec = 0x5f
-)
-
-// OpcodeAtomic represents an opcode of atomic instructions which has
-// multi-byte encoding and is prefixed by OpcodeAtomicPrefix.
-//
-// These opcodes are toggled with CoreFeaturesThreads.
-type OpcodeAtomic = byte
-
-const (
- // OpcodeAtomicMemoryNotify represents the instruction memory.atomic.notify.
- OpcodeAtomicMemoryNotify OpcodeAtomic = 0x00
- // OpcodeAtomicMemoryWait32 represents the instruction memory.atomic.wait32.
- OpcodeAtomicMemoryWait32 OpcodeAtomic = 0x01
- // OpcodeAtomicMemoryWait64 represents the instruction memory.atomic.wait64.
- OpcodeAtomicMemoryWait64 OpcodeAtomic = 0x02
- // OpcodeAtomicFence represents the instruction atomic.fence.
- OpcodeAtomicFence OpcodeAtomic = 0x03
-
- // OpcodeAtomicI32Load represents the instruction i32.atomic.load.
- OpcodeAtomicI32Load OpcodeAtomic = 0x10
- // OpcodeAtomicI64Load represents the instruction i64.atomic.load.
- OpcodeAtomicI64Load OpcodeAtomic = 0x11
- // OpcodeAtomicI32Load8U represents the instruction i32.atomic.load8_u.
- OpcodeAtomicI32Load8U OpcodeAtomic = 0x12
- // OpcodeAtomicI32Load16U represents the instruction i32.atomic.load16_u.
- OpcodeAtomicI32Load16U OpcodeAtomic = 0x13
- // OpcodeAtomicI64Load8U represents the instruction i64.atomic.load8_u.
- OpcodeAtomicI64Load8U OpcodeAtomic = 0x14
- // OpcodeAtomicI64Load16U represents the instruction i64.atomic.load16_u.
- OpcodeAtomicI64Load16U OpcodeAtomic = 0x15
- // OpcodeAtomicI64Load32U represents the instruction i64.atomic.load32_u.
- OpcodeAtomicI64Load32U OpcodeAtomic = 0x16
- // OpcodeAtomicI32Store represents the instruction i32.atomic.store.
- OpcodeAtomicI32Store OpcodeAtomic = 0x17
- // OpcodeAtomicI64Store represents the instruction i64.atomic.store.
- OpcodeAtomicI64Store OpcodeAtomic = 0x18
- // OpcodeAtomicI32Store8 represents the instruction i32.atomic.store8.
- OpcodeAtomicI32Store8 OpcodeAtomic = 0x19
- // OpcodeAtomicI32Store16 represents the instruction i32.atomic.store16.
- OpcodeAtomicI32Store16 OpcodeAtomic = 0x1a
- // OpcodeAtomicI64Store8 represents the instruction i64.atomic.store8.
- OpcodeAtomicI64Store8 OpcodeAtomic = 0x1b
- // OpcodeAtomicI64Store16 represents the instruction i64.atomic.store16.
- OpcodeAtomicI64Store16 OpcodeAtomic = 0x1c
- // OpcodeAtomicI64Store32 represents the instruction i64.atomic.store32.
- OpcodeAtomicI64Store32 OpcodeAtomic = 0x1d
-
- // OpcodeAtomicI32RmwAdd represents the instruction i32.atomic.rmw.add.
- OpcodeAtomicI32RmwAdd OpcodeAtomic = 0x1e
- // OpcodeAtomicI64RmwAdd represents the instruction i64.atomic.rmw.add.
- OpcodeAtomicI64RmwAdd OpcodeAtomic = 0x1f
- // OpcodeAtomicI32Rmw8AddU represents the instruction i32.atomic.rmw8.add_u.
- OpcodeAtomicI32Rmw8AddU OpcodeAtomic = 0x20
- // OpcodeAtomicI32Rmw16AddU represents the instruction i32.atomic.rmw16.add_u.
- OpcodeAtomicI32Rmw16AddU OpcodeAtomic = 0x21
- // OpcodeAtomicI64Rmw8AddU represents the instruction i64.atomic.rmw8.add_u.
- OpcodeAtomicI64Rmw8AddU OpcodeAtomic = 0x22
- // OpcodeAtomicI64Rmw16AddU represents the instruction i64.atomic.rmw16.add_u.
- OpcodeAtomicI64Rmw16AddU OpcodeAtomic = 0x23
- // OpcodeAtomicI64Rmw32AddU represents the instruction i64.atomic.rmw32.add_u.
- OpcodeAtomicI64Rmw32AddU OpcodeAtomic = 0x24
-
- // OpcodeAtomicI32RmwSub represents the instruction i32.atomic.rmw.sub.
- OpcodeAtomicI32RmwSub OpcodeAtomic = 0x25
- // OpcodeAtomicI64RmwSub represents the instruction i64.atomic.rmw.sub.
- OpcodeAtomicI64RmwSub OpcodeAtomic = 0x26
- // OpcodeAtomicI32Rmw8SubU represents the instruction i32.atomic.rmw8.sub_u.
- OpcodeAtomicI32Rmw8SubU OpcodeAtomic = 0x27
- // OpcodeAtomicI32Rmw16SubU represents the instruction i32.atomic.rmw16.sub_u.
- OpcodeAtomicI32Rmw16SubU OpcodeAtomic = 0x28
- // OpcodeAtomicI64Rmw8SubU represents the instruction i64.atomic.rmw8.sub_u.
- OpcodeAtomicI64Rmw8SubU OpcodeAtomic = 0x29
- // OpcodeAtomicI64Rmw16SubU represents the instruction i64.atomic.rmw16.sub_u.
- OpcodeAtomicI64Rmw16SubU OpcodeAtomic = 0x2a
- // OpcodeAtomicI64Rmw32SubU represents the instruction i64.atomic.rmw32.sub_u.
- OpcodeAtomicI64Rmw32SubU OpcodeAtomic = 0x2b
-
- // OpcodeAtomicI32RmwAnd represents the instruction i32.atomic.rmw.and.
- OpcodeAtomicI32RmwAnd OpcodeAtomic = 0x2c
- // OpcodeAtomicI64RmwAnd represents the instruction i64.atomic.rmw.and.
- OpcodeAtomicI64RmwAnd OpcodeAtomic = 0x2d
- // OpcodeAtomicI32Rmw8AndU represents the instruction i32.atomic.rmw8.and_u.
- OpcodeAtomicI32Rmw8AndU OpcodeAtomic = 0x2e
- // OpcodeAtomicI32Rmw16AndU represents the instruction i32.atomic.rmw16.and_u.
- OpcodeAtomicI32Rmw16AndU OpcodeAtomic = 0x2f
- // OpcodeAtomicI64Rmw8AndU represents the instruction i64.atomic.rmw8.and_u.
- OpcodeAtomicI64Rmw8AndU OpcodeAtomic = 0x30
- // OpcodeAtomicI64Rmw16AndU represents the instruction i64.atomic.rmw16.and_u.
- OpcodeAtomicI64Rmw16AndU OpcodeAtomic = 0x31
- // OpcodeAtomicI64Rmw32AndU represents the instruction i64.atomic.rmw32.and_u.
- OpcodeAtomicI64Rmw32AndU OpcodeAtomic = 0x32
-
- // OpcodeAtomicI32RmwOr represents the instruction i32.atomic.rmw.or.
- OpcodeAtomicI32RmwOr OpcodeAtomic = 0x33
- // OpcodeAtomicI64RmwOr represents the instruction i64.atomic.rmw.or.
- OpcodeAtomicI64RmwOr OpcodeAtomic = 0x34
- // OpcodeAtomicI32Rmw8OrU represents the instruction i32.atomic.rmw8.or_u.
- OpcodeAtomicI32Rmw8OrU OpcodeAtomic = 0x35
- // OpcodeAtomicI32Rmw16OrU represents the instruction i32.atomic.rmw16.or_u.
- OpcodeAtomicI32Rmw16OrU OpcodeAtomic = 0x36
- // OpcodeAtomicI64Rmw8OrU represents the instruction i64.atomic.rmw8.or_u.
- OpcodeAtomicI64Rmw8OrU OpcodeAtomic = 0x37
- // OpcodeAtomicI64Rmw16OrU represents the instruction i64.atomic.rmw16.or_u.
- OpcodeAtomicI64Rmw16OrU OpcodeAtomic = 0x38
- // OpcodeAtomicI64Rmw32OrU represents the instruction i64.atomic.rmw32.or_u.
- OpcodeAtomicI64Rmw32OrU OpcodeAtomic = 0x39
-
- // OpcodeAtomicI32RmwXor represents the instruction i32.atomic.rmw.xor.
- OpcodeAtomicI32RmwXor OpcodeAtomic = 0x3a
- // OpcodeAtomicI64RmwXor represents the instruction i64.atomic.rmw.xor.
- OpcodeAtomicI64RmwXor OpcodeAtomic = 0x3b
- // OpcodeAtomicI32Rmw8XorU represents the instruction i32.atomic.rmw8.xor_u.
- OpcodeAtomicI32Rmw8XorU OpcodeAtomic = 0x3c
- // OpcodeAtomicI32Rmw16XorU represents the instruction i32.atomic.rmw16.xor_u.
- OpcodeAtomicI32Rmw16XorU OpcodeAtomic = 0x3d
- // OpcodeAtomicI64Rmw8XorU represents the instruction i64.atomic.rmw8.xor_u.
- OpcodeAtomicI64Rmw8XorU OpcodeAtomic = 0x3e
- // OpcodeAtomicI64Rmw16XorU represents the instruction i64.atomic.rmw16.xor_u.
- OpcodeAtomicI64Rmw16XorU OpcodeAtomic = 0x3f
- // OpcodeAtomicI64Rmw32XorU represents the instruction i64.atomic.rmw32.xor_u.
- OpcodeAtomicI64Rmw32XorU OpcodeAtomic = 0x40
-
- // OpcodeAtomicI32RmwXchg represents the instruction i32.atomic.rmw.xchg.
- OpcodeAtomicI32RmwXchg OpcodeAtomic = 0x41
- // OpcodeAtomicI64RmwXchg represents the instruction i64.atomic.rmw.xchg.
- OpcodeAtomicI64RmwXchg OpcodeAtomic = 0x42
- // OpcodeAtomicI32Rmw8XchgU represents the instruction i32.atomic.rmw8.xchg_u.
- OpcodeAtomicI32Rmw8XchgU OpcodeAtomic = 0x43
- // OpcodeAtomicI32Rmw16XchgU represents the instruction i32.atomic.rmw16.xchg_u.
- OpcodeAtomicI32Rmw16XchgU OpcodeAtomic = 0x44
- // OpcodeAtomicI64Rmw8XchgU represents the instruction i64.atomic.rmw8.xchg_u.
- OpcodeAtomicI64Rmw8XchgU OpcodeAtomic = 0x45
- // OpcodeAtomicI64Rmw16XchgU represents the instruction i64.atomic.rmw16.xchg_u.
- OpcodeAtomicI64Rmw16XchgU OpcodeAtomic = 0x46
- // OpcodeAtomicI64Rmw32XchgU represents the instruction i64.atomic.rmw32.xchg_u.
- OpcodeAtomicI64Rmw32XchgU OpcodeAtomic = 0x47
-
- // OpcodeAtomicI32RmwCmpxchg represents the instruction i32.atomic.rmw.cmpxchg.
- OpcodeAtomicI32RmwCmpxchg OpcodeAtomic = 0x48
- // OpcodeAtomicI64RmwCmpxchg represents the instruction i64.atomic.rmw.cmpxchg.
- OpcodeAtomicI64RmwCmpxchg OpcodeAtomic = 0x49
- // OpcodeAtomicI32Rmw8CmpxchgU represents the instruction i32.atomic.rmw8.cmpxchg_u.
- OpcodeAtomicI32Rmw8CmpxchgU OpcodeAtomic = 0x4a
- // OpcodeAtomicI32Rmw16CmpxchgU represents the instruction i32.atomic.rmw16.cmpxchg_u.
- OpcodeAtomicI32Rmw16CmpxchgU OpcodeAtomic = 0x4b
- // OpcodeAtomicI64Rmw8CmpxchgU represents the instruction i64.atomic.rmw8.cmpxchg_u.
- OpcodeAtomicI64Rmw8CmpxchgU OpcodeAtomic = 0x4c
- // OpcodeAtomicI64Rmw16CmpxchgU represents the instruction i64.atomic.rmw16.cmpxchg_u.
- OpcodeAtomicI64Rmw16CmpxchgU OpcodeAtomic = 0x4d
- // OpcodeAtomicI64Rmw32CmpxchgU represents the instruction i64.atomic.rmw32.cmpxchg_u.
- OpcodeAtomicI64Rmw32CmpxchgU OpcodeAtomic = 0x4e
-)
-
-const (
- OpcodeUnreachableName = "unreachable"
- OpcodeNopName = "nop"
- OpcodeBlockName = "block"
- OpcodeLoopName = "loop"
- OpcodeIfName = "if"
- OpcodeElseName = "else"
- OpcodeEndName = "end"
- OpcodeBrName = "br"
- OpcodeBrIfName = "br_if"
- OpcodeBrTableName = "br_table"
- OpcodeReturnName = "return"
- OpcodeCallName = "call"
- OpcodeCallIndirectName = "call_indirect"
- OpcodeDropName = "drop"
- OpcodeSelectName = "select"
- OpcodeTypedSelectName = "typed_select"
- OpcodeLocalGetName = "local.get"
- OpcodeLocalSetName = "local.set"
- OpcodeLocalTeeName = "local.tee"
- OpcodeGlobalGetName = "global.get"
- OpcodeGlobalSetName = "global.set"
- OpcodeI32LoadName = "i32.load"
- OpcodeI64LoadName = "i64.load"
- OpcodeF32LoadName = "f32.load"
- OpcodeF64LoadName = "f64.load"
- OpcodeI32Load8SName = "i32.load8_s"
- OpcodeI32Load8UName = "i32.load8_u"
- OpcodeI32Load16SName = "i32.load16_s"
- OpcodeI32Load16UName = "i32.load16_u"
- OpcodeI64Load8SName = "i64.load8_s"
- OpcodeI64Load8UName = "i64.load8_u"
- OpcodeI64Load16SName = "i64.load16_s"
- OpcodeI64Load16UName = "i64.load16_u"
- OpcodeI64Load32SName = "i64.load32_s"
- OpcodeI64Load32UName = "i64.load32_u"
- OpcodeI32StoreName = "i32.store"
- OpcodeI64StoreName = "i64.store"
- OpcodeF32StoreName = "f32.store"
- OpcodeF64StoreName = "f64.store"
- OpcodeI32Store8Name = "i32.store8"
- OpcodeI32Store16Name = "i32.store16"
- OpcodeI64Store8Name = "i64.store8"
- OpcodeI64Store16Name = "i64.store16"
- OpcodeI64Store32Name = "i64.store32"
- OpcodeMemorySizeName = "memory.size"
- OpcodeMemoryGrowName = "memory.grow"
- OpcodeI32ConstName = "i32.const"
- OpcodeI64ConstName = "i64.const"
- OpcodeF32ConstName = "f32.const"
- OpcodeF64ConstName = "f64.const"
- OpcodeI32EqzName = "i32.eqz"
- OpcodeI32EqName = "i32.eq"
- OpcodeI32NeName = "i32.ne"
- OpcodeI32LtSName = "i32.lt_s"
- OpcodeI32LtUName = "i32.lt_u"
- OpcodeI32GtSName = "i32.gt_s"
- OpcodeI32GtUName = "i32.gt_u"
- OpcodeI32LeSName = "i32.le_s"
- OpcodeI32LeUName = "i32.le_u"
- OpcodeI32GeSName = "i32.ge_s"
- OpcodeI32GeUName = "i32.ge_u"
- OpcodeI64EqzName = "i64.eqz"
- OpcodeI64EqName = "i64.eq"
- OpcodeI64NeName = "i64.ne"
- OpcodeI64LtSName = "i64.lt_s"
- OpcodeI64LtUName = "i64.lt_u"
- OpcodeI64GtSName = "i64.gt_s"
- OpcodeI64GtUName = "i64.gt_u"
- OpcodeI64LeSName = "i64.le_s"
- OpcodeI64LeUName = "i64.le_u"
- OpcodeI64GeSName = "i64.ge_s"
- OpcodeI64GeUName = "i64.ge_u"
- OpcodeF32EqName = "f32.eq"
- OpcodeF32NeName = "f32.ne"
- OpcodeF32LtName = "f32.lt"
- OpcodeF32GtName = "f32.gt"
- OpcodeF32LeName = "f32.le"
- OpcodeF32GeName = "f32.ge"
- OpcodeF64EqName = "f64.eq"
- OpcodeF64NeName = "f64.ne"
- OpcodeF64LtName = "f64.lt"
- OpcodeF64GtName = "f64.gt"
- OpcodeF64LeName = "f64.le"
- OpcodeF64GeName = "f64.ge"
- OpcodeI32ClzName = "i32.clz"
- OpcodeI32CtzName = "i32.ctz"
- OpcodeI32PopcntName = "i32.popcnt"
- OpcodeI32AddName = "i32.add"
- OpcodeI32SubName = "i32.sub"
- OpcodeI32MulName = "i32.mul"
- OpcodeI32DivSName = "i32.div_s"
- OpcodeI32DivUName = "i32.div_u"
- OpcodeI32RemSName = "i32.rem_s"
- OpcodeI32RemUName = "i32.rem_u"
- OpcodeI32AndName = "i32.and"
- OpcodeI32OrName = "i32.or"
- OpcodeI32XorName = "i32.xor"
- OpcodeI32ShlName = "i32.shl"
- OpcodeI32ShrSName = "i32.shr_s"
- OpcodeI32ShrUName = "i32.shr_u"
- OpcodeI32RotlName = "i32.rotl"
- OpcodeI32RotrName = "i32.rotr"
- OpcodeI64ClzName = "i64.clz"
- OpcodeI64CtzName = "i64.ctz"
- OpcodeI64PopcntName = "i64.popcnt"
- OpcodeI64AddName = "i64.add"
- OpcodeI64SubName = "i64.sub"
- OpcodeI64MulName = "i64.mul"
- OpcodeI64DivSName = "i64.div_s"
- OpcodeI64DivUName = "i64.div_u"
- OpcodeI64RemSName = "i64.rem_s"
- OpcodeI64RemUName = "i64.rem_u"
- OpcodeI64AndName = "i64.and"
- OpcodeI64OrName = "i64.or"
- OpcodeI64XorName = "i64.xor"
- OpcodeI64ShlName = "i64.shl"
- OpcodeI64ShrSName = "i64.shr_s"
- OpcodeI64ShrUName = "i64.shr_u"
- OpcodeI64RotlName = "i64.rotl"
- OpcodeI64RotrName = "i64.rotr"
- OpcodeF32AbsName = "f32.abs"
- OpcodeF32NegName = "f32.neg"
- OpcodeF32CeilName = "f32.ceil"
- OpcodeF32FloorName = "f32.floor"
- OpcodeF32TruncName = "f32.trunc"
- OpcodeF32NearestName = "f32.nearest"
- OpcodeF32SqrtName = "f32.sqrt"
- OpcodeF32AddName = "f32.add"
- OpcodeF32SubName = "f32.sub"
- OpcodeF32MulName = "f32.mul"
- OpcodeF32DivName = "f32.div"
- OpcodeF32MinName = "f32.min"
- OpcodeF32MaxName = "f32.max"
- OpcodeF32CopysignName = "f32.copysign"
- OpcodeF64AbsName = "f64.abs"
- OpcodeF64NegName = "f64.neg"
- OpcodeF64CeilName = "f64.ceil"
- OpcodeF64FloorName = "f64.floor"
- OpcodeF64TruncName = "f64.trunc"
- OpcodeF64NearestName = "f64.nearest"
- OpcodeF64SqrtName = "f64.sqrt"
- OpcodeF64AddName = "f64.add"
- OpcodeF64SubName = "f64.sub"
- OpcodeF64MulName = "f64.mul"
- OpcodeF64DivName = "f64.div"
- OpcodeF64MinName = "f64.min"
- OpcodeF64MaxName = "f64.max"
- OpcodeF64CopysignName = "f64.copysign"
- OpcodeI32WrapI64Name = "i32.wrap_i64"
- OpcodeI32TruncF32SName = "i32.trunc_f32_s"
- OpcodeI32TruncF32UName = "i32.trunc_f32_u"
- OpcodeI32TruncF64SName = "i32.trunc_f64_s"
- OpcodeI32TruncF64UName = "i32.trunc_f64_u"
- OpcodeI64ExtendI32SName = "i64.extend_i32_s"
- OpcodeI64ExtendI32UName = "i64.extend_i32_u"
- OpcodeI64TruncF32SName = "i64.trunc_f32_s"
- OpcodeI64TruncF32UName = "i64.trunc_f32_u"
- OpcodeI64TruncF64SName = "i64.trunc_f64_s"
- OpcodeI64TruncF64UName = "i64.trunc_f64_u"
- OpcodeF32ConvertI32SName = "f32.convert_i32_s"
- OpcodeF32ConvertI32UName = "f32.convert_i32_u"
- OpcodeF32ConvertI64SName = "f32.convert_i64_s"
- OpcodeF32ConvertI64UName = "f32.convert_i64u"
- OpcodeF32DemoteF64Name = "f32.demote_f64"
- OpcodeF64ConvertI32SName = "f64.convert_i32_s"
- OpcodeF64ConvertI32UName = "f64.convert_i32_u"
- OpcodeF64ConvertI64SName = "f64.convert_i64_s"
- OpcodeF64ConvertI64UName = "f64.convert_i64_u"
- OpcodeF64PromoteF32Name = "f64.promote_f32"
- OpcodeI32ReinterpretF32Name = "i32.reinterpret_f32"
- OpcodeI64ReinterpretF64Name = "i64.reinterpret_f64"
- OpcodeF32ReinterpretI32Name = "f32.reinterpret_i32"
- OpcodeF64ReinterpretI64Name = "f64.reinterpret_i64"
-
- OpcodeRefNullName = "ref.null"
- OpcodeRefIsNullName = "ref.is_null"
- OpcodeRefFuncName = "ref.func"
-
- OpcodeTableGetName = "table.get"
- OpcodeTableSetName = "table.set"
-
- // Below are toggled with CoreFeatureSignExtensionOps
-
- OpcodeI32Extend8SName = "i32.extend8_s"
- OpcodeI32Extend16SName = "i32.extend16_s"
- OpcodeI64Extend8SName = "i64.extend8_s"
- OpcodeI64Extend16SName = "i64.extend16_s"
- OpcodeI64Extend32SName = "i64.extend32_s"
-
- OpcodeMiscPrefixName = "misc_prefix"
- OpcodeVecPrefixName = "vector_prefix"
- OpcodeAtomicPrefixName = "atomic_prefix"
-)
-
-var instructionNames = [256]string{
- OpcodeUnreachable: OpcodeUnreachableName,
- OpcodeNop: OpcodeNopName,
- OpcodeBlock: OpcodeBlockName,
- OpcodeLoop: OpcodeLoopName,
- OpcodeIf: OpcodeIfName,
- OpcodeElse: OpcodeElseName,
- OpcodeEnd: OpcodeEndName,
- OpcodeBr: OpcodeBrName,
- OpcodeBrIf: OpcodeBrIfName,
- OpcodeBrTable: OpcodeBrTableName,
- OpcodeReturn: OpcodeReturnName,
- OpcodeCall: OpcodeCallName,
- OpcodeCallIndirect: OpcodeCallIndirectName,
- OpcodeDrop: OpcodeDropName,
- OpcodeSelect: OpcodeSelectName,
- OpcodeTypedSelect: OpcodeTypedSelectName,
- OpcodeLocalGet: OpcodeLocalGetName,
- OpcodeLocalSet: OpcodeLocalSetName,
- OpcodeLocalTee: OpcodeLocalTeeName,
- OpcodeGlobalGet: OpcodeGlobalGetName,
- OpcodeGlobalSet: OpcodeGlobalSetName,
- OpcodeI32Load: OpcodeI32LoadName,
- OpcodeI64Load: OpcodeI64LoadName,
- OpcodeF32Load: OpcodeF32LoadName,
- OpcodeF64Load: OpcodeF64LoadName,
- OpcodeI32Load8S: OpcodeI32Load8SName,
- OpcodeI32Load8U: OpcodeI32Load8UName,
- OpcodeI32Load16S: OpcodeI32Load16SName,
- OpcodeI32Load16U: OpcodeI32Load16UName,
- OpcodeI64Load8S: OpcodeI64Load8SName,
- OpcodeI64Load8U: OpcodeI64Load8UName,
- OpcodeI64Load16S: OpcodeI64Load16SName,
- OpcodeI64Load16U: OpcodeI64Load16UName,
- OpcodeI64Load32S: OpcodeI64Load32SName,
- OpcodeI64Load32U: OpcodeI64Load32UName,
- OpcodeI32Store: OpcodeI32StoreName,
- OpcodeI64Store: OpcodeI64StoreName,
- OpcodeF32Store: OpcodeF32StoreName,
- OpcodeF64Store: OpcodeF64StoreName,
- OpcodeI32Store8: OpcodeI32Store8Name,
- OpcodeI32Store16: OpcodeI32Store16Name,
- OpcodeI64Store8: OpcodeI64Store8Name,
- OpcodeI64Store16: OpcodeI64Store16Name,
- OpcodeI64Store32: OpcodeI64Store32Name,
- OpcodeMemorySize: OpcodeMemorySizeName,
- OpcodeMemoryGrow: OpcodeMemoryGrowName,
- OpcodeI32Const: OpcodeI32ConstName,
- OpcodeI64Const: OpcodeI64ConstName,
- OpcodeF32Const: OpcodeF32ConstName,
- OpcodeF64Const: OpcodeF64ConstName,
- OpcodeI32Eqz: OpcodeI32EqzName,
- OpcodeI32Eq: OpcodeI32EqName,
- OpcodeI32Ne: OpcodeI32NeName,
- OpcodeI32LtS: OpcodeI32LtSName,
- OpcodeI32LtU: OpcodeI32LtUName,
- OpcodeI32GtS: OpcodeI32GtSName,
- OpcodeI32GtU: OpcodeI32GtUName,
- OpcodeI32LeS: OpcodeI32LeSName,
- OpcodeI32LeU: OpcodeI32LeUName,
- OpcodeI32GeS: OpcodeI32GeSName,
- OpcodeI32GeU: OpcodeI32GeUName,
- OpcodeI64Eqz: OpcodeI64EqzName,
- OpcodeI64Eq: OpcodeI64EqName,
- OpcodeI64Ne: OpcodeI64NeName,
- OpcodeI64LtS: OpcodeI64LtSName,
- OpcodeI64LtU: OpcodeI64LtUName,
- OpcodeI64GtS: OpcodeI64GtSName,
- OpcodeI64GtU: OpcodeI64GtUName,
- OpcodeI64LeS: OpcodeI64LeSName,
- OpcodeI64LeU: OpcodeI64LeUName,
- OpcodeI64GeS: OpcodeI64GeSName,
- OpcodeI64GeU: OpcodeI64GeUName,
- OpcodeF32Eq: OpcodeF32EqName,
- OpcodeF32Ne: OpcodeF32NeName,
- OpcodeF32Lt: OpcodeF32LtName,
- OpcodeF32Gt: OpcodeF32GtName,
- OpcodeF32Le: OpcodeF32LeName,
- OpcodeF32Ge: OpcodeF32GeName,
- OpcodeF64Eq: OpcodeF64EqName,
- OpcodeF64Ne: OpcodeF64NeName,
- OpcodeF64Lt: OpcodeF64LtName,
- OpcodeF64Gt: OpcodeF64GtName,
- OpcodeF64Le: OpcodeF64LeName,
- OpcodeF64Ge: OpcodeF64GeName,
- OpcodeI32Clz: OpcodeI32ClzName,
- OpcodeI32Ctz: OpcodeI32CtzName,
- OpcodeI32Popcnt: OpcodeI32PopcntName,
- OpcodeI32Add: OpcodeI32AddName,
- OpcodeI32Sub: OpcodeI32SubName,
- OpcodeI32Mul: OpcodeI32MulName,
- OpcodeI32DivS: OpcodeI32DivSName,
- OpcodeI32DivU: OpcodeI32DivUName,
- OpcodeI32RemS: OpcodeI32RemSName,
- OpcodeI32RemU: OpcodeI32RemUName,
- OpcodeI32And: OpcodeI32AndName,
- OpcodeI32Or: OpcodeI32OrName,
- OpcodeI32Xor: OpcodeI32XorName,
- OpcodeI32Shl: OpcodeI32ShlName,
- OpcodeI32ShrS: OpcodeI32ShrSName,
- OpcodeI32ShrU: OpcodeI32ShrUName,
- OpcodeI32Rotl: OpcodeI32RotlName,
- OpcodeI32Rotr: OpcodeI32RotrName,
- OpcodeI64Clz: OpcodeI64ClzName,
- OpcodeI64Ctz: OpcodeI64CtzName,
- OpcodeI64Popcnt: OpcodeI64PopcntName,
- OpcodeI64Add: OpcodeI64AddName,
- OpcodeI64Sub: OpcodeI64SubName,
- OpcodeI64Mul: OpcodeI64MulName,
- OpcodeI64DivS: OpcodeI64DivSName,
- OpcodeI64DivU: OpcodeI64DivUName,
- OpcodeI64RemS: OpcodeI64RemSName,
- OpcodeI64RemU: OpcodeI64RemUName,
- OpcodeI64And: OpcodeI64AndName,
- OpcodeI64Or: OpcodeI64OrName,
- OpcodeI64Xor: OpcodeI64XorName,
- OpcodeI64Shl: OpcodeI64ShlName,
- OpcodeI64ShrS: OpcodeI64ShrSName,
- OpcodeI64ShrU: OpcodeI64ShrUName,
- OpcodeI64Rotl: OpcodeI64RotlName,
- OpcodeI64Rotr: OpcodeI64RotrName,
- OpcodeF32Abs: OpcodeF32AbsName,
- OpcodeF32Neg: OpcodeF32NegName,
- OpcodeF32Ceil: OpcodeF32CeilName,
- OpcodeF32Floor: OpcodeF32FloorName,
- OpcodeF32Trunc: OpcodeF32TruncName,
- OpcodeF32Nearest: OpcodeF32NearestName,
- OpcodeF32Sqrt: OpcodeF32SqrtName,
- OpcodeF32Add: OpcodeF32AddName,
- OpcodeF32Sub: OpcodeF32SubName,
- OpcodeF32Mul: OpcodeF32MulName,
- OpcodeF32Div: OpcodeF32DivName,
- OpcodeF32Min: OpcodeF32MinName,
- OpcodeF32Max: OpcodeF32MaxName,
- OpcodeF32Copysign: OpcodeF32CopysignName,
- OpcodeF64Abs: OpcodeF64AbsName,
- OpcodeF64Neg: OpcodeF64NegName,
- OpcodeF64Ceil: OpcodeF64CeilName,
- OpcodeF64Floor: OpcodeF64FloorName,
- OpcodeF64Trunc: OpcodeF64TruncName,
- OpcodeF64Nearest: OpcodeF64NearestName,
- OpcodeF64Sqrt: OpcodeF64SqrtName,
- OpcodeF64Add: OpcodeF64AddName,
- OpcodeF64Sub: OpcodeF64SubName,
- OpcodeF64Mul: OpcodeF64MulName,
- OpcodeF64Div: OpcodeF64DivName,
- OpcodeF64Min: OpcodeF64MinName,
- OpcodeF64Max: OpcodeF64MaxName,
- OpcodeF64Copysign: OpcodeF64CopysignName,
- OpcodeI32WrapI64: OpcodeI32WrapI64Name,
- OpcodeI32TruncF32S: OpcodeI32TruncF32SName,
- OpcodeI32TruncF32U: OpcodeI32TruncF32UName,
- OpcodeI32TruncF64S: OpcodeI32TruncF64SName,
- OpcodeI32TruncF64U: OpcodeI32TruncF64UName,
- OpcodeI64ExtendI32S: OpcodeI64ExtendI32SName,
- OpcodeI64ExtendI32U: OpcodeI64ExtendI32UName,
- OpcodeI64TruncF32S: OpcodeI64TruncF32SName,
- OpcodeI64TruncF32U: OpcodeI64TruncF32UName,
- OpcodeI64TruncF64S: OpcodeI64TruncF64SName,
- OpcodeI64TruncF64U: OpcodeI64TruncF64UName,
- OpcodeF32ConvertI32S: OpcodeF32ConvertI32SName,
- OpcodeF32ConvertI32U: OpcodeF32ConvertI32UName,
- OpcodeF32ConvertI64S: OpcodeF32ConvertI64SName,
- OpcodeF32ConvertI64U: OpcodeF32ConvertI64UName,
- OpcodeF32DemoteF64: OpcodeF32DemoteF64Name,
- OpcodeF64ConvertI32S: OpcodeF64ConvertI32SName,
- OpcodeF64ConvertI32U: OpcodeF64ConvertI32UName,
- OpcodeF64ConvertI64S: OpcodeF64ConvertI64SName,
- OpcodeF64ConvertI64U: OpcodeF64ConvertI64UName,
- OpcodeF64PromoteF32: OpcodeF64PromoteF32Name,
- OpcodeI32ReinterpretF32: OpcodeI32ReinterpretF32Name,
- OpcodeI64ReinterpretF64: OpcodeI64ReinterpretF64Name,
- OpcodeF32ReinterpretI32: OpcodeF32ReinterpretI32Name,
- OpcodeF64ReinterpretI64: OpcodeF64ReinterpretI64Name,
-
- OpcodeRefNull: OpcodeRefNullName,
- OpcodeRefIsNull: OpcodeRefIsNullName,
- OpcodeRefFunc: OpcodeRefFuncName,
-
- OpcodeTableGet: OpcodeTableGetName,
- OpcodeTableSet: OpcodeTableSetName,
-
- // Below are toggled with CoreFeatureSignExtensionOps
-
- OpcodeI32Extend8S: OpcodeI32Extend8SName,
- OpcodeI32Extend16S: OpcodeI32Extend16SName,
- OpcodeI64Extend8S: OpcodeI64Extend8SName,
- OpcodeI64Extend16S: OpcodeI64Extend16SName,
- OpcodeI64Extend32S: OpcodeI64Extend32SName,
-
- OpcodeMiscPrefix: OpcodeMiscPrefixName,
- OpcodeVecPrefix: OpcodeVecPrefixName,
-}
-
-// InstructionName returns the instruction corresponding to this binary Opcode.
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#a7-index-of-instructions
-func InstructionName(oc Opcode) string {
- return instructionNames[oc]
-}
-
-const (
- OpcodeI32TruncSatF32SName = "i32.trunc_sat_f32_s"
- OpcodeI32TruncSatF32UName = "i32.trunc_sat_f32_u"
- OpcodeI32TruncSatF64SName = "i32.trunc_sat_f64_s"
- OpcodeI32TruncSatF64UName = "i32.trunc_sat_f64_u"
- OpcodeI64TruncSatF32SName = "i64.trunc_sat_f32_s"
- OpcodeI64TruncSatF32UName = "i64.trunc_sat_f32_u"
- OpcodeI64TruncSatF64SName = "i64.trunc_sat_f64_s"
- OpcodeI64TruncSatF64UName = "i64.trunc_sat_f64_u"
-
- OpcodeMemoryInitName = "memory.init"
- OpcodeDataDropName = "data.drop"
- OpcodeMemoryCopyName = "memory.copy"
- OpcodeMemoryFillName = "memory.fill"
- OpcodeTableInitName = "table.init"
- OpcodeElemDropName = "elem.drop"
- OpcodeTableCopyName = "table.copy"
- OpcodeTableGrowName = "table.grow"
- OpcodeTableSizeName = "table.size"
- OpcodeTableFillName = "table.fill"
-)
-
-var miscInstructionNames = [256]string{
- OpcodeMiscI32TruncSatF32S: OpcodeI32TruncSatF32SName,
- OpcodeMiscI32TruncSatF32U: OpcodeI32TruncSatF32UName,
- OpcodeMiscI32TruncSatF64S: OpcodeI32TruncSatF64SName,
- OpcodeMiscI32TruncSatF64U: OpcodeI32TruncSatF64UName,
- OpcodeMiscI64TruncSatF32S: OpcodeI64TruncSatF32SName,
- OpcodeMiscI64TruncSatF32U: OpcodeI64TruncSatF32UName,
- OpcodeMiscI64TruncSatF64S: OpcodeI64TruncSatF64SName,
- OpcodeMiscI64TruncSatF64U: OpcodeI64TruncSatF64UName,
-
- OpcodeMiscMemoryInit: OpcodeMemoryInitName,
- OpcodeMiscDataDrop: OpcodeDataDropName,
- OpcodeMiscMemoryCopy: OpcodeMemoryCopyName,
- OpcodeMiscMemoryFill: OpcodeMemoryFillName,
- OpcodeMiscTableInit: OpcodeTableInitName,
- OpcodeMiscElemDrop: OpcodeElemDropName,
- OpcodeMiscTableCopy: OpcodeTableCopyName,
- OpcodeMiscTableGrow: OpcodeTableGrowName,
- OpcodeMiscTableSize: OpcodeTableSizeName,
- OpcodeMiscTableFill: OpcodeTableFillName,
-}
-
-// MiscInstructionName returns the instruction corresponding to this miscellaneous Opcode.
-func MiscInstructionName(oc OpcodeMisc) string {
- return miscInstructionNames[oc]
-}
-
-const (
- OpcodeVecV128LoadName = "v128.load"
- OpcodeVecV128Load8x8SName = "v128.load8x8_s"
- OpcodeVecV128Load8x8UName = "v128.load8x8_u"
- OpcodeVecV128Load16x4SName = "v128.load16x4_s"
- OpcodeVecV128Load16x4UName = "v128.load16x4_u"
- OpcodeVecV128Load32x2SName = "v128.load32x2_s"
- OpcodeVecV128Load32x2UName = "v128.load32x2_u"
- OpcodeVecV128Load8SplatName = "v128.load8_splat"
- OpcodeVecV128Load16SplatName = "v128.load16_splat"
- OpcodeVecV128Load32SplatName = "v128.load32_splat"
- OpcodeVecV128Load64SplatName = "v128.load64_splat"
- OpcodeVecV128Load32zeroName = "v128.load32_zero"
- OpcodeVecV128Load64zeroName = "v128.load64_zero"
- OpcodeVecV128StoreName = "v128.store"
- OpcodeVecV128Load8LaneName = "v128.load8_lane"
- OpcodeVecV128Load16LaneName = "v128.load16_lane"
- OpcodeVecV128Load32LaneName = "v128.load32_lane"
- OpcodeVecV128Load64LaneName = "v128.load64_lane"
- OpcodeVecV128Store8LaneName = "v128.store8_lane"
- OpcodeVecV128Store16LaneName = "v128.store16_lane"
- OpcodeVecV128Store32LaneName = "v128.store32_lane"
- OpcodeVecV128Store64LaneName = "v128.store64_lane"
- OpcodeVecV128ConstName = "v128.const"
- OpcodeVecV128i8x16ShuffleName = "v128.shuffle"
- OpcodeVecI8x16ExtractLaneSName = "i8x16.extract_lane_s"
- OpcodeVecI8x16ExtractLaneUName = "i8x16.extract_lane_u"
- OpcodeVecI8x16ReplaceLaneName = "i8x16.replace_lane"
- OpcodeVecI16x8ExtractLaneSName = "i16x8.extract_lane_s"
- OpcodeVecI16x8ExtractLaneUName = "i16x8.extract_lane_u"
- OpcodeVecI16x8ReplaceLaneName = "i16x8.replace_lane"
- OpcodeVecI32x4ExtractLaneName = "i32x4.extract_lane"
- OpcodeVecI32x4ReplaceLaneName = "i32x4.replace_lane"
- OpcodeVecI64x2ExtractLaneName = "i64x2.extract_lane"
- OpcodeVecI64x2ReplaceLaneName = "i64x2.replace_lane"
- OpcodeVecF32x4ExtractLaneName = "f32x4.extract_lane"
- OpcodeVecF32x4ReplaceLaneName = "f32x4.replace_lane"
- OpcodeVecF64x2ExtractLaneName = "f64x2.extract_lane"
- OpcodeVecF64x2ReplaceLaneName = "f64x2.replace_lane"
- OpcodeVecI8x16SwizzleName = "i8x16.swizzle"
- OpcodeVecI8x16SplatName = "i8x16.splat"
- OpcodeVecI16x8SplatName = "i16x8.splat"
- OpcodeVecI32x4SplatName = "i32x4.splat"
- OpcodeVecI64x2SplatName = "i64x2.splat"
- OpcodeVecF32x4SplatName = "f32x4.splat"
- OpcodeVecF64x2SplatName = "f64x2.splat"
- OpcodeVecI8x16EqName = "i8x16.eq"
- OpcodeVecI8x16NeName = "i8x16.ne"
- OpcodeVecI8x16LtSName = "i8x16.lt_s"
- OpcodeVecI8x16LtUName = "i8x16.lt_u"
- OpcodeVecI8x16GtSName = "i8x16.gt_s"
- OpcodeVecI8x16GtUName = "i8x16.gt_u"
- OpcodeVecI8x16LeSName = "i8x16.le_s"
- OpcodeVecI8x16LeUName = "i8x16.le_u"
- OpcodeVecI8x16GeSName = "i8x16.ge_s"
- OpcodeVecI8x16GeUName = "i8x16.ge_u"
- OpcodeVecI16x8EqName = "i16x8.eq"
- OpcodeVecI16x8NeName = "i16x8.ne"
- OpcodeVecI16x8LtSName = "i16x8.lt_s"
- OpcodeVecI16x8LtUName = "i16x8.lt_u"
- OpcodeVecI16x8GtSName = "i16x8.gt_s"
- OpcodeVecI16x8GtUName = "i16x8.gt_u"
- OpcodeVecI16x8LeSName = "i16x8.le_s"
- OpcodeVecI16x8LeUName = "i16x8.le_u"
- OpcodeVecI16x8GeSName = "i16x8.ge_s"
- OpcodeVecI16x8GeUName = "i16x8.ge_u"
- OpcodeVecI32x4EqName = "i32x4.eq"
- OpcodeVecI32x4NeName = "i32x4.ne"
- OpcodeVecI32x4LtSName = "i32x4.lt_s"
- OpcodeVecI32x4LtUName = "i32x4.lt_u"
- OpcodeVecI32x4GtSName = "i32x4.gt_s"
- OpcodeVecI32x4GtUName = "i32x4.gt_u"
- OpcodeVecI32x4LeSName = "i32x4.le_s"
- OpcodeVecI32x4LeUName = "i32x4.le_u"
- OpcodeVecI32x4GeSName = "i32x4.ge_s"
- OpcodeVecI32x4GeUName = "i32x4.ge_u"
- OpcodeVecI64x2EqName = "i64x2.eq"
- OpcodeVecI64x2NeName = "i64x2.ne"
- OpcodeVecI64x2LtSName = "i64x2.lt"
- OpcodeVecI64x2GtSName = "i64x2.gt"
- OpcodeVecI64x2LeSName = "i64x2.le"
- OpcodeVecI64x2GeSName = "i64x2.ge"
- OpcodeVecF32x4EqName = "f32x4.eq"
- OpcodeVecF32x4NeName = "f32x4.ne"
- OpcodeVecF32x4LtName = "f32x4.lt"
- OpcodeVecF32x4GtName = "f32x4.gt"
- OpcodeVecF32x4LeName = "f32x4.le"
- OpcodeVecF32x4GeName = "f32x4.ge"
- OpcodeVecF64x2EqName = "f64x2.eq"
- OpcodeVecF64x2NeName = "f64x2.ne"
- OpcodeVecF64x2LtName = "f64x2.lt"
- OpcodeVecF64x2GtName = "f64x2.gt"
- OpcodeVecF64x2LeName = "f64x2.le"
- OpcodeVecF64x2GeName = "f64x2.ge"
- OpcodeVecV128NotName = "v128.not"
- OpcodeVecV128AndName = "v128.and"
- OpcodeVecV128AndNotName = "v128.andnot"
- OpcodeVecV128OrName = "v128.or"
- OpcodeVecV128XorName = "v128.xor"
- OpcodeVecV128BitselectName = "v128.bitselect"
- OpcodeVecV128AnyTrueName = "v128.any_true"
- OpcodeVecI8x16AbsName = "i8x16.abs"
- OpcodeVecI8x16NegName = "i8x16.neg"
- OpcodeVecI8x16PopcntName = "i8x16.popcnt"
- OpcodeVecI8x16AllTrueName = "i8x16.all_true"
- OpcodeVecI8x16BitMaskName = "i8x16.bitmask"
- OpcodeVecI8x16NarrowI16x8SName = "i8x16.narrow_i16x8_s"
- OpcodeVecI8x16NarrowI16x8UName = "i8x16.narrow_i16x8_u"
- OpcodeVecI8x16ShlName = "i8x16.shl"
- OpcodeVecI8x16ShrSName = "i8x16.shr_s"
- OpcodeVecI8x16ShrUName = "i8x16.shr_u"
- OpcodeVecI8x16AddName = "i8x16.add"
- OpcodeVecI8x16AddSatSName = "i8x16.add_sat_s"
- OpcodeVecI8x16AddSatUName = "i8x16.add_sat_u"
- OpcodeVecI8x16SubName = "i8x16.sub"
- OpcodeVecI8x16SubSatSName = "i8x16.sub_s"
- OpcodeVecI8x16SubSatUName = "i8x16.sub_u"
- OpcodeVecI8x16MinSName = "i8x16.min_s"
- OpcodeVecI8x16MinUName = "i8x16.min_u"
- OpcodeVecI8x16MaxSName = "i8x16.max_s"
- OpcodeVecI8x16MaxUName = "i8x16.max_u"
- OpcodeVecI8x16AvgrUName = "i8x16.avgr_u"
- OpcodeVecI16x8ExtaddPairwiseI8x16SName = "i16x8.extadd_pairwise_i8x16_s"
- OpcodeVecI16x8ExtaddPairwiseI8x16UName = "i16x8.extadd_pairwise_i8x16_u"
- OpcodeVecI16x8AbsName = "i16x8.abs"
- OpcodeVecI16x8NegName = "i16x8.neg"
- OpcodeVecI16x8Q15mulrSatSName = "i16x8.q15mulr_sat_s"
- OpcodeVecI16x8AllTrueName = "i16x8.all_true"
- OpcodeVecI16x8BitMaskName = "i16x8.bitmask"
- OpcodeVecI16x8NarrowI32x4SName = "i16x8.narrow_i32x4_s"
- OpcodeVecI16x8NarrowI32x4UName = "i16x8.narrow_i32x4_u"
- OpcodeVecI16x8ExtendLowI8x16SName = "i16x8.extend_low_i8x16_s"
- OpcodeVecI16x8ExtendHighI8x16SName = "i16x8.extend_high_i8x16_s"
- OpcodeVecI16x8ExtendLowI8x16UName = "i16x8.extend_low_i8x16_u"
- OpcodeVecI16x8ExtendHighI8x16UName = "i16x8.extend_high_i8x16_u"
- OpcodeVecI16x8ShlName = "i16x8.shl"
- OpcodeVecI16x8ShrSName = "i16x8.shr_s"
- OpcodeVecI16x8ShrUName = "i16x8.shr_u"
- OpcodeVecI16x8AddName = "i16x8.add"
- OpcodeVecI16x8AddSatSName = "i16x8.add_sat_s"
- OpcodeVecI16x8AddSatUName = "i16x8.add_sat_u"
- OpcodeVecI16x8SubName = "i16x8.sub"
- OpcodeVecI16x8SubSatSName = "i16x8.sub_sat_s"
- OpcodeVecI16x8SubSatUName = "i16x8.sub_sat_u"
- OpcodeVecI16x8MulName = "i16x8.mul"
- OpcodeVecI16x8MinSName = "i16x8.min_s"
- OpcodeVecI16x8MinUName = "i16x8.min_u"
- OpcodeVecI16x8MaxSName = "i16x8.max_s"
- OpcodeVecI16x8MaxUName = "i16x8.max_u"
- OpcodeVecI16x8AvgrUName = "i16x8.avgr_u"
- OpcodeVecI16x8ExtMulLowI8x16SName = "i16x8.extmul_low_i8x16_s"
- OpcodeVecI16x8ExtMulHighI8x16SName = "i16x8.extmul_high_i8x16_s"
- OpcodeVecI16x8ExtMulLowI8x16UName = "i16x8.extmul_low_i8x16_u"
- OpcodeVecI16x8ExtMulHighI8x16UName = "i16x8.extmul_high_i8x16_u"
- OpcodeVecI32x4ExtaddPairwiseI16x8SName = "i32x4.extadd_pairwise_i16x8_s"
- OpcodeVecI32x4ExtaddPairwiseI16x8UName = "i32x4.extadd_pairwise_i16x8_u"
- OpcodeVecI32x4AbsName = "i32x4.abs"
- OpcodeVecI32x4NegName = "i32x4.neg"
- OpcodeVecI32x4AllTrueName = "i32x4.all_true"
- OpcodeVecI32x4BitMaskName = "i32x4.bitmask"
- OpcodeVecI32x4ExtendLowI16x8SName = "i32x4.extend_low_i16x8_s"
- OpcodeVecI32x4ExtendHighI16x8SName = "i32x4.extend_high_i16x8_s"
- OpcodeVecI32x4ExtendLowI16x8UName = "i32x4.extend_low_i16x8_u"
- OpcodeVecI32x4ExtendHighI16x8UName = "i32x4.extend_high_i16x8_u"
- OpcodeVecI32x4ShlName = "i32x4.shl"
- OpcodeVecI32x4ShrSName = "i32x4.shr_s"
- OpcodeVecI32x4ShrUName = "i32x4.shr_u"
- OpcodeVecI32x4AddName = "i32x4.add"
- OpcodeVecI32x4SubName = "i32x4.sub"
- OpcodeVecI32x4MulName = "i32x4.mul"
- OpcodeVecI32x4MinSName = "i32x4.min_s"
- OpcodeVecI32x4MinUName = "i32x4.min_u"
- OpcodeVecI32x4MaxSName = "i32x4.max_s"
- OpcodeVecI32x4MaxUName = "i32x4.max_u"
- OpcodeVecI32x4DotI16x8SName = "i32x4.dot_i16x8_s"
- OpcodeVecI32x4ExtMulLowI16x8SName = "i32x4.extmul_low_i16x8_s"
- OpcodeVecI32x4ExtMulHighI16x8SName = "i32x4.extmul_high_i16x8_s"
- OpcodeVecI32x4ExtMulLowI16x8UName = "i32x4.extmul_low_i16x8_u"
- OpcodeVecI32x4ExtMulHighI16x8UName = "i32x4.extmul_high_i16x8_u"
- OpcodeVecI64x2AbsName = "i64x2.abs"
- OpcodeVecI64x2NegName = "i64x2.neg"
- OpcodeVecI64x2AllTrueName = "i64x2.all_true"
- OpcodeVecI64x2BitMaskName = "i64x2.bitmask"
- OpcodeVecI64x2ExtendLowI32x4SName = "i64x2.extend_low_i32x4_s"
- OpcodeVecI64x2ExtendHighI32x4SName = "i64x2.extend_high_i32x4_s"
- OpcodeVecI64x2ExtendLowI32x4UName = "i64x2.extend_low_i32x4_u"
- OpcodeVecI64x2ExtendHighI32x4UName = "i64x2.extend_high_i32x4_u"
- OpcodeVecI64x2ShlName = "i64x2.shl"
- OpcodeVecI64x2ShrSName = "i64x2.shr_s"
- OpcodeVecI64x2ShrUName = "i64x2.shr_u"
- OpcodeVecI64x2AddName = "i64x2.add"
- OpcodeVecI64x2SubName = "i64x2.sub"
- OpcodeVecI64x2MulName = "i64x2.mul"
- OpcodeVecI64x2ExtMulLowI32x4SName = "i64x2.extmul_low_i32x4_s"
- OpcodeVecI64x2ExtMulHighI32x4SName = "i64x2.extmul_high_i32x4_s"
- OpcodeVecI64x2ExtMulLowI32x4UName = "i64x2.extmul_low_i32x4_u"
- OpcodeVecI64x2ExtMulHighI32x4UName = "i64x2.extmul_high_i32x4_u"
- OpcodeVecF32x4CeilName = "f32x4.ceil"
- OpcodeVecF32x4FloorName = "f32x4.floor"
- OpcodeVecF32x4TruncName = "f32x4.trunc"
- OpcodeVecF32x4NearestName = "f32x4.nearest"
- OpcodeVecF32x4AbsName = "f32x4.abs"
- OpcodeVecF32x4NegName = "f32x4.neg"
- OpcodeVecF32x4SqrtName = "f32x4.sqrt"
- OpcodeVecF32x4AddName = "f32x4.add"
- OpcodeVecF32x4SubName = "f32x4.sub"
- OpcodeVecF32x4MulName = "f32x4.mul"
- OpcodeVecF32x4DivName = "f32x4.div"
- OpcodeVecF32x4MinName = "f32x4.min"
- OpcodeVecF32x4MaxName = "f32x4.max"
- OpcodeVecF32x4PminName = "f32x4.pmin"
- OpcodeVecF32x4PmaxName = "f32x4.pmax"
- OpcodeVecF64x2CeilName = "f64x2.ceil"
- OpcodeVecF64x2FloorName = "f64x2.floor"
- OpcodeVecF64x2TruncName = "f64x2.trunc"
- OpcodeVecF64x2NearestName = "f64x2.nearest"
- OpcodeVecF64x2AbsName = "f64x2.abs"
- OpcodeVecF64x2NegName = "f64x2.neg"
- OpcodeVecF64x2SqrtName = "f64x2.sqrt"
- OpcodeVecF64x2AddName = "f64x2.add"
- OpcodeVecF64x2SubName = "f64x2.sub"
- OpcodeVecF64x2MulName = "f64x2.mul"
- OpcodeVecF64x2DivName = "f64x2.div"
- OpcodeVecF64x2MinName = "f64x2.min"
- OpcodeVecF64x2MaxName = "f64x2.max"
- OpcodeVecF64x2PminName = "f64x2.pmin"
- OpcodeVecF64x2PmaxName = "f64x2.pmax"
- OpcodeVecI32x4TruncSatF32x4SName = "i32x4.trunc_sat_f32x4_s"
- OpcodeVecI32x4TruncSatF32x4UName = "i32x4.trunc_sat_f32x4_u"
- OpcodeVecF32x4ConvertI32x4SName = "f32x4.convert_i32x4_s"
- OpcodeVecF32x4ConvertI32x4UName = "f32x4.convert_i32x4_u"
- OpcodeVecI32x4TruncSatF64x2SZeroName = "i32x4.trunc_sat_f64x2_s_zero"
- OpcodeVecI32x4TruncSatF64x2UZeroName = "i32x4.trunc_sat_f64x2_u_zero"
- OpcodeVecF64x2ConvertLowI32x4SName = "f64x2.convert_low_i32x4_s"
- OpcodeVecF64x2ConvertLowI32x4UName = "f64x2.convert_low_i32x4_u"
- OpcodeVecF32x4DemoteF64x2ZeroName = "f32x4.demote_f64x2_zero"
- OpcodeVecF64x2PromoteLowF32x4ZeroName = "f64x2.promote_low_f32x4"
-)
-
-var vectorInstructionName = map[OpcodeVec]string{
- OpcodeVecV128Load: OpcodeVecV128LoadName,
- OpcodeVecV128Load8x8s: OpcodeVecV128Load8x8SName,
- OpcodeVecV128Load8x8u: OpcodeVecV128Load8x8UName,
- OpcodeVecV128Load16x4s: OpcodeVecV128Load16x4SName,
- OpcodeVecV128Load16x4u: OpcodeVecV128Load16x4UName,
- OpcodeVecV128Load32x2s: OpcodeVecV128Load32x2SName,
- OpcodeVecV128Load32x2u: OpcodeVecV128Load32x2UName,
- OpcodeVecV128Load8Splat: OpcodeVecV128Load8SplatName,
- OpcodeVecV128Load16Splat: OpcodeVecV128Load16SplatName,
- OpcodeVecV128Load32Splat: OpcodeVecV128Load32SplatName,
- OpcodeVecV128Load64Splat: OpcodeVecV128Load64SplatName,
- OpcodeVecV128Load32zero: OpcodeVecV128Load32zeroName,
- OpcodeVecV128Load64zero: OpcodeVecV128Load64zeroName,
- OpcodeVecV128Store: OpcodeVecV128StoreName,
- OpcodeVecV128Load8Lane: OpcodeVecV128Load8LaneName,
- OpcodeVecV128Load16Lane: OpcodeVecV128Load16LaneName,
- OpcodeVecV128Load32Lane: OpcodeVecV128Load32LaneName,
- OpcodeVecV128Load64Lane: OpcodeVecV128Load64LaneName,
- OpcodeVecV128Store8Lane: OpcodeVecV128Store8LaneName,
- OpcodeVecV128Store16Lane: OpcodeVecV128Store16LaneName,
- OpcodeVecV128Store32Lane: OpcodeVecV128Store32LaneName,
- OpcodeVecV128Store64Lane: OpcodeVecV128Store64LaneName,
- OpcodeVecV128Const: OpcodeVecV128ConstName,
- OpcodeVecV128i8x16Shuffle: OpcodeVecV128i8x16ShuffleName,
- OpcodeVecI8x16ExtractLaneS: OpcodeVecI8x16ExtractLaneSName,
- OpcodeVecI8x16ExtractLaneU: OpcodeVecI8x16ExtractLaneUName,
- OpcodeVecI8x16ReplaceLane: OpcodeVecI8x16ReplaceLaneName,
- OpcodeVecI16x8ExtractLaneS: OpcodeVecI16x8ExtractLaneSName,
- OpcodeVecI16x8ExtractLaneU: OpcodeVecI16x8ExtractLaneUName,
- OpcodeVecI16x8ReplaceLane: OpcodeVecI16x8ReplaceLaneName,
- OpcodeVecI32x4ExtractLane: OpcodeVecI32x4ExtractLaneName,
- OpcodeVecI32x4ReplaceLane: OpcodeVecI32x4ReplaceLaneName,
- OpcodeVecI64x2ExtractLane: OpcodeVecI64x2ExtractLaneName,
- OpcodeVecI64x2ReplaceLane: OpcodeVecI64x2ReplaceLaneName,
- OpcodeVecF32x4ExtractLane: OpcodeVecF32x4ExtractLaneName,
- OpcodeVecF32x4ReplaceLane: OpcodeVecF32x4ReplaceLaneName,
- OpcodeVecF64x2ExtractLane: OpcodeVecF64x2ExtractLaneName,
- OpcodeVecF64x2ReplaceLane: OpcodeVecF64x2ReplaceLaneName,
- OpcodeVecI8x16Swizzle: OpcodeVecI8x16SwizzleName,
- OpcodeVecI8x16Splat: OpcodeVecI8x16SplatName,
- OpcodeVecI16x8Splat: OpcodeVecI16x8SplatName,
- OpcodeVecI32x4Splat: OpcodeVecI32x4SplatName,
- OpcodeVecI64x2Splat: OpcodeVecI64x2SplatName,
- OpcodeVecF32x4Splat: OpcodeVecF32x4SplatName,
- OpcodeVecF64x2Splat: OpcodeVecF64x2SplatName,
- OpcodeVecI8x16Eq: OpcodeVecI8x16EqName,
- OpcodeVecI8x16Ne: OpcodeVecI8x16NeName,
- OpcodeVecI8x16LtS: OpcodeVecI8x16LtSName,
- OpcodeVecI8x16LtU: OpcodeVecI8x16LtUName,
- OpcodeVecI8x16GtS: OpcodeVecI8x16GtSName,
- OpcodeVecI8x16GtU: OpcodeVecI8x16GtUName,
- OpcodeVecI8x16LeS: OpcodeVecI8x16LeSName,
- OpcodeVecI8x16LeU: OpcodeVecI8x16LeUName,
- OpcodeVecI8x16GeS: OpcodeVecI8x16GeSName,
- OpcodeVecI8x16GeU: OpcodeVecI8x16GeUName,
- OpcodeVecI16x8Eq: OpcodeVecI16x8EqName,
- OpcodeVecI16x8Ne: OpcodeVecI16x8NeName,
- OpcodeVecI16x8LtS: OpcodeVecI16x8LtSName,
- OpcodeVecI16x8LtU: OpcodeVecI16x8LtUName,
- OpcodeVecI16x8GtS: OpcodeVecI16x8GtSName,
- OpcodeVecI16x8GtU: OpcodeVecI16x8GtUName,
- OpcodeVecI16x8LeS: OpcodeVecI16x8LeSName,
- OpcodeVecI16x8LeU: OpcodeVecI16x8LeUName,
- OpcodeVecI16x8GeS: OpcodeVecI16x8GeSName,
- OpcodeVecI16x8GeU: OpcodeVecI16x8GeUName,
- OpcodeVecI32x4Eq: OpcodeVecI32x4EqName,
- OpcodeVecI32x4Ne: OpcodeVecI32x4NeName,
- OpcodeVecI32x4LtS: OpcodeVecI32x4LtSName,
- OpcodeVecI32x4LtU: OpcodeVecI32x4LtUName,
- OpcodeVecI32x4GtS: OpcodeVecI32x4GtSName,
- OpcodeVecI32x4GtU: OpcodeVecI32x4GtUName,
- OpcodeVecI32x4LeS: OpcodeVecI32x4LeSName,
- OpcodeVecI32x4LeU: OpcodeVecI32x4LeUName,
- OpcodeVecI32x4GeS: OpcodeVecI32x4GeSName,
- OpcodeVecI32x4GeU: OpcodeVecI32x4GeUName,
- OpcodeVecI64x2Eq: OpcodeVecI64x2EqName,
- OpcodeVecI64x2Ne: OpcodeVecI64x2NeName,
- OpcodeVecI64x2LtS: OpcodeVecI64x2LtSName,
- OpcodeVecI64x2GtS: OpcodeVecI64x2GtSName,
- OpcodeVecI64x2LeS: OpcodeVecI64x2LeSName,
- OpcodeVecI64x2GeS: OpcodeVecI64x2GeSName,
- OpcodeVecF32x4Eq: OpcodeVecF32x4EqName,
- OpcodeVecF32x4Ne: OpcodeVecF32x4NeName,
- OpcodeVecF32x4Lt: OpcodeVecF32x4LtName,
- OpcodeVecF32x4Gt: OpcodeVecF32x4GtName,
- OpcodeVecF32x4Le: OpcodeVecF32x4LeName,
- OpcodeVecF32x4Ge: OpcodeVecF32x4GeName,
- OpcodeVecF64x2Eq: OpcodeVecF64x2EqName,
- OpcodeVecF64x2Ne: OpcodeVecF64x2NeName,
- OpcodeVecF64x2Lt: OpcodeVecF64x2LtName,
- OpcodeVecF64x2Gt: OpcodeVecF64x2GtName,
- OpcodeVecF64x2Le: OpcodeVecF64x2LeName,
- OpcodeVecF64x2Ge: OpcodeVecF64x2GeName,
- OpcodeVecV128Not: OpcodeVecV128NotName,
- OpcodeVecV128And: OpcodeVecV128AndName,
- OpcodeVecV128AndNot: OpcodeVecV128AndNotName,
- OpcodeVecV128Or: OpcodeVecV128OrName,
- OpcodeVecV128Xor: OpcodeVecV128XorName,
- OpcodeVecV128Bitselect: OpcodeVecV128BitselectName,
- OpcodeVecV128AnyTrue: OpcodeVecV128AnyTrueName,
- OpcodeVecI8x16Abs: OpcodeVecI8x16AbsName,
- OpcodeVecI8x16Neg: OpcodeVecI8x16NegName,
- OpcodeVecI8x16Popcnt: OpcodeVecI8x16PopcntName,
- OpcodeVecI8x16AllTrue: OpcodeVecI8x16AllTrueName,
- OpcodeVecI8x16BitMask: OpcodeVecI8x16BitMaskName,
- OpcodeVecI8x16NarrowI16x8S: OpcodeVecI8x16NarrowI16x8SName,
- OpcodeVecI8x16NarrowI16x8U: OpcodeVecI8x16NarrowI16x8UName,
- OpcodeVecI8x16Shl: OpcodeVecI8x16ShlName,
- OpcodeVecI8x16ShrS: OpcodeVecI8x16ShrSName,
- OpcodeVecI8x16ShrU: OpcodeVecI8x16ShrUName,
- OpcodeVecI8x16Add: OpcodeVecI8x16AddName,
- OpcodeVecI8x16AddSatS: OpcodeVecI8x16AddSatSName,
- OpcodeVecI8x16AddSatU: OpcodeVecI8x16AddSatUName,
- OpcodeVecI8x16Sub: OpcodeVecI8x16SubName,
- OpcodeVecI8x16SubSatS: OpcodeVecI8x16SubSatSName,
- OpcodeVecI8x16SubSatU: OpcodeVecI8x16SubSatUName,
- OpcodeVecI8x16MinS: OpcodeVecI8x16MinSName,
- OpcodeVecI8x16MinU: OpcodeVecI8x16MinUName,
- OpcodeVecI8x16MaxS: OpcodeVecI8x16MaxSName,
- OpcodeVecI8x16MaxU: OpcodeVecI8x16MaxUName,
- OpcodeVecI8x16AvgrU: OpcodeVecI8x16AvgrUName,
- OpcodeVecI16x8ExtaddPairwiseI8x16S: OpcodeVecI16x8ExtaddPairwiseI8x16SName,
- OpcodeVecI16x8ExtaddPairwiseI8x16U: OpcodeVecI16x8ExtaddPairwiseI8x16UName,
- OpcodeVecI16x8Abs: OpcodeVecI16x8AbsName,
- OpcodeVecI16x8Neg: OpcodeVecI16x8NegName,
- OpcodeVecI16x8Q15mulrSatS: OpcodeVecI16x8Q15mulrSatSName,
- OpcodeVecI16x8AllTrue: OpcodeVecI16x8AllTrueName,
- OpcodeVecI16x8BitMask: OpcodeVecI16x8BitMaskName,
- OpcodeVecI16x8NarrowI32x4S: OpcodeVecI16x8NarrowI32x4SName,
- OpcodeVecI16x8NarrowI32x4U: OpcodeVecI16x8NarrowI32x4UName,
- OpcodeVecI16x8ExtendLowI8x16S: OpcodeVecI16x8ExtendLowI8x16SName,
- OpcodeVecI16x8ExtendHighI8x16S: OpcodeVecI16x8ExtendHighI8x16SName,
- OpcodeVecI16x8ExtendLowI8x16U: OpcodeVecI16x8ExtendLowI8x16UName,
- OpcodeVecI16x8ExtendHighI8x16U: OpcodeVecI16x8ExtendHighI8x16UName,
- OpcodeVecI16x8Shl: OpcodeVecI16x8ShlName,
- OpcodeVecI16x8ShrS: OpcodeVecI16x8ShrSName,
- OpcodeVecI16x8ShrU: OpcodeVecI16x8ShrUName,
- OpcodeVecI16x8Add: OpcodeVecI16x8AddName,
- OpcodeVecI16x8AddSatS: OpcodeVecI16x8AddSatSName,
- OpcodeVecI16x8AddSatU: OpcodeVecI16x8AddSatUName,
- OpcodeVecI16x8Sub: OpcodeVecI16x8SubName,
- OpcodeVecI16x8SubSatS: OpcodeVecI16x8SubSatSName,
- OpcodeVecI16x8SubSatU: OpcodeVecI16x8SubSatUName,
- OpcodeVecI16x8Mul: OpcodeVecI16x8MulName,
- OpcodeVecI16x8MinS: OpcodeVecI16x8MinSName,
- OpcodeVecI16x8MinU: OpcodeVecI16x8MinUName,
- OpcodeVecI16x8MaxS: OpcodeVecI16x8MaxSName,
- OpcodeVecI16x8MaxU: OpcodeVecI16x8MaxUName,
- OpcodeVecI16x8AvgrU: OpcodeVecI16x8AvgrUName,
- OpcodeVecI16x8ExtMulLowI8x16S: OpcodeVecI16x8ExtMulLowI8x16SName,
- OpcodeVecI16x8ExtMulHighI8x16S: OpcodeVecI16x8ExtMulHighI8x16SName,
- OpcodeVecI16x8ExtMulLowI8x16U: OpcodeVecI16x8ExtMulLowI8x16UName,
- OpcodeVecI16x8ExtMulHighI8x16U: OpcodeVecI16x8ExtMulHighI8x16UName,
- OpcodeVecI32x4ExtaddPairwiseI16x8S: OpcodeVecI32x4ExtaddPairwiseI16x8SName,
- OpcodeVecI32x4ExtaddPairwiseI16x8U: OpcodeVecI32x4ExtaddPairwiseI16x8UName,
- OpcodeVecI32x4Abs: OpcodeVecI32x4AbsName,
- OpcodeVecI32x4Neg: OpcodeVecI32x4NegName,
- OpcodeVecI32x4AllTrue: OpcodeVecI32x4AllTrueName,
- OpcodeVecI32x4BitMask: OpcodeVecI32x4BitMaskName,
- OpcodeVecI32x4ExtendLowI16x8S: OpcodeVecI32x4ExtendLowI16x8SName,
- OpcodeVecI32x4ExtendHighI16x8S: OpcodeVecI32x4ExtendHighI16x8SName,
- OpcodeVecI32x4ExtendLowI16x8U: OpcodeVecI32x4ExtendLowI16x8UName,
- OpcodeVecI32x4ExtendHighI16x8U: OpcodeVecI32x4ExtendHighI16x8UName,
- OpcodeVecI32x4Shl: OpcodeVecI32x4ShlName,
- OpcodeVecI32x4ShrS: OpcodeVecI32x4ShrSName,
- OpcodeVecI32x4ShrU: OpcodeVecI32x4ShrUName,
- OpcodeVecI32x4Add: OpcodeVecI32x4AddName,
- OpcodeVecI32x4Sub: OpcodeVecI32x4SubName,
- OpcodeVecI32x4Mul: OpcodeVecI32x4MulName,
- OpcodeVecI32x4MinS: OpcodeVecI32x4MinSName,
- OpcodeVecI32x4MinU: OpcodeVecI32x4MinUName,
- OpcodeVecI32x4MaxS: OpcodeVecI32x4MaxSName,
- OpcodeVecI32x4MaxU: OpcodeVecI32x4MaxUName,
- OpcodeVecI32x4DotI16x8S: OpcodeVecI32x4DotI16x8SName,
- OpcodeVecI32x4ExtMulLowI16x8S: OpcodeVecI32x4ExtMulLowI16x8SName,
- OpcodeVecI32x4ExtMulHighI16x8S: OpcodeVecI32x4ExtMulHighI16x8SName,
- OpcodeVecI32x4ExtMulLowI16x8U: OpcodeVecI32x4ExtMulLowI16x8UName,
- OpcodeVecI32x4ExtMulHighI16x8U: OpcodeVecI32x4ExtMulHighI16x8UName,
- OpcodeVecI64x2Abs: OpcodeVecI64x2AbsName,
- OpcodeVecI64x2Neg: OpcodeVecI64x2NegName,
- OpcodeVecI64x2AllTrue: OpcodeVecI64x2AllTrueName,
- OpcodeVecI64x2BitMask: OpcodeVecI64x2BitMaskName,
- OpcodeVecI64x2ExtendLowI32x4S: OpcodeVecI64x2ExtendLowI32x4SName,
- OpcodeVecI64x2ExtendHighI32x4S: OpcodeVecI64x2ExtendHighI32x4SName,
- OpcodeVecI64x2ExtendLowI32x4U: OpcodeVecI64x2ExtendLowI32x4UName,
- OpcodeVecI64x2ExtendHighI32x4U: OpcodeVecI64x2ExtendHighI32x4UName,
- OpcodeVecI64x2Shl: OpcodeVecI64x2ShlName,
- OpcodeVecI64x2ShrS: OpcodeVecI64x2ShrSName,
- OpcodeVecI64x2ShrU: OpcodeVecI64x2ShrUName,
- OpcodeVecI64x2Add: OpcodeVecI64x2AddName,
- OpcodeVecI64x2Sub: OpcodeVecI64x2SubName,
- OpcodeVecI64x2Mul: OpcodeVecI64x2MulName,
- OpcodeVecI64x2ExtMulLowI32x4S: OpcodeVecI64x2ExtMulLowI32x4SName,
- OpcodeVecI64x2ExtMulHighI32x4S: OpcodeVecI64x2ExtMulHighI32x4SName,
- OpcodeVecI64x2ExtMulLowI32x4U: OpcodeVecI64x2ExtMulLowI32x4UName,
- OpcodeVecI64x2ExtMulHighI32x4U: OpcodeVecI64x2ExtMulHighI32x4UName,
- OpcodeVecF32x4Ceil: OpcodeVecF32x4CeilName,
- OpcodeVecF32x4Floor: OpcodeVecF32x4FloorName,
- OpcodeVecF32x4Trunc: OpcodeVecF32x4TruncName,
- OpcodeVecF32x4Nearest: OpcodeVecF32x4NearestName,
- OpcodeVecF32x4Abs: OpcodeVecF32x4AbsName,
- OpcodeVecF32x4Neg: OpcodeVecF32x4NegName,
- OpcodeVecF32x4Sqrt: OpcodeVecF32x4SqrtName,
- OpcodeVecF32x4Add: OpcodeVecF32x4AddName,
- OpcodeVecF32x4Sub: OpcodeVecF32x4SubName,
- OpcodeVecF32x4Mul: OpcodeVecF32x4MulName,
- OpcodeVecF32x4Div: OpcodeVecF32x4DivName,
- OpcodeVecF32x4Min: OpcodeVecF32x4MinName,
- OpcodeVecF32x4Max: OpcodeVecF32x4MaxName,
- OpcodeVecF32x4Pmin: OpcodeVecF32x4PminName,
- OpcodeVecF32x4Pmax: OpcodeVecF32x4PmaxName,
- OpcodeVecF64x2Ceil: OpcodeVecF64x2CeilName,
- OpcodeVecF64x2Floor: OpcodeVecF64x2FloorName,
- OpcodeVecF64x2Trunc: OpcodeVecF64x2TruncName,
- OpcodeVecF64x2Nearest: OpcodeVecF64x2NearestName,
- OpcodeVecF64x2Abs: OpcodeVecF64x2AbsName,
- OpcodeVecF64x2Neg: OpcodeVecF64x2NegName,
- OpcodeVecF64x2Sqrt: OpcodeVecF64x2SqrtName,
- OpcodeVecF64x2Add: OpcodeVecF64x2AddName,
- OpcodeVecF64x2Sub: OpcodeVecF64x2SubName,
- OpcodeVecF64x2Mul: OpcodeVecF64x2MulName,
- OpcodeVecF64x2Div: OpcodeVecF64x2DivName,
- OpcodeVecF64x2Min: OpcodeVecF64x2MinName,
- OpcodeVecF64x2Max: OpcodeVecF64x2MaxName,
- OpcodeVecF64x2Pmin: OpcodeVecF64x2PminName,
- OpcodeVecF64x2Pmax: OpcodeVecF64x2PmaxName,
- OpcodeVecI32x4TruncSatF32x4S: OpcodeVecI32x4TruncSatF32x4SName,
- OpcodeVecI32x4TruncSatF32x4U: OpcodeVecI32x4TruncSatF32x4UName,
- OpcodeVecF32x4ConvertI32x4S: OpcodeVecF32x4ConvertI32x4SName,
- OpcodeVecF32x4ConvertI32x4U: OpcodeVecF32x4ConvertI32x4UName,
- OpcodeVecI32x4TruncSatF64x2SZero: OpcodeVecI32x4TruncSatF64x2SZeroName,
- OpcodeVecI32x4TruncSatF64x2UZero: OpcodeVecI32x4TruncSatF64x2UZeroName,
- OpcodeVecF64x2ConvertLowI32x4S: OpcodeVecF64x2ConvertLowI32x4SName,
- OpcodeVecF64x2ConvertLowI32x4U: OpcodeVecF64x2ConvertLowI32x4UName,
- OpcodeVecF32x4DemoteF64x2Zero: OpcodeVecF32x4DemoteF64x2ZeroName,
- OpcodeVecF64x2PromoteLowF32x4Zero: OpcodeVecF64x2PromoteLowF32x4ZeroName,
-}
-
-// VectorInstructionName returns the instruction name corresponding to the vector Opcode.
-func VectorInstructionName(oc OpcodeVec) (ret string) {
- return vectorInstructionName[oc]
-}
-
-const (
- OpcodeAtomicMemoryNotifyName = "memory.atomic.notify"
- OpcodeAtomicMemoryWait32Name = "memory.atomic.wait32"
- OpcodeAtomicMemoryWait64Name = "memory.atomic.wait64"
- OpcodeAtomicFenceName = "atomic.fence"
-
- OpcodeAtomicI32LoadName = "i32.atomic.load"
- OpcodeAtomicI64LoadName = "i64.atomic.load"
- OpcodeAtomicI32Load8UName = "i32.atomic.load8_u"
- OpcodeAtomicI32Load16UName = "i32.atomic.load16_u"
- OpcodeAtomicI64Load8UName = "i64.atomic.load8_u"
- OpcodeAtomicI64Load16UName = "i64.atomic.load16_u"
- OpcodeAtomicI64Load32UName = "i64.atomic.load32_u"
- OpcodeAtomicI32StoreName = "i32.atomic.store"
- OpcodeAtomicI64StoreName = "i64.atomic.store"
- OpcodeAtomicI32Store8Name = "i32.atomic.store8"
- OpcodeAtomicI32Store16Name = "i32.atomic.store16"
- OpcodeAtomicI64Store8Name = "i64.atomic.store8"
- OpcodeAtomicI64Store16Name = "i64.atomic.store16"
- OpcodeAtomicI64Store32Name = "i64.atomic.store32"
-
- OpcodeAtomicI32RmwAddName = "i32.atomic.rmw.add"
- OpcodeAtomicI64RmwAddName = "i64.atomic.rmw.add"
- OpcodeAtomicI32Rmw8AddUName = "i32.atomic.rmw8.add_u"
- OpcodeAtomicI32Rmw16AddUName = "i32.atomic.rmw16.add_u"
- OpcodeAtomicI64Rmw8AddUName = "i64.atomic.rmw8.add_u"
- OpcodeAtomicI64Rmw16AddUName = "i64.atomic.rmw16.add_u"
- OpcodeAtomicI64Rmw32AddUName = "i64.atomic.rmw32.add_u"
-
- OpcodeAtomicI32RmwSubName = "i32.atomic.rmw.sub"
- OpcodeAtomicI64RmwSubName = "i64.atomic.rmw.sub"
- OpcodeAtomicI32Rmw8SubUName = "i32.atomic.rmw8.sub_u"
- OpcodeAtomicI32Rmw16SubUName = "i32.atomic.rmw16.sub_u"
- OpcodeAtomicI64Rmw8SubUName = "i64.atomic.rmw8.sub_u"
- OpcodeAtomicI64Rmw16SubUName = "i64.atomic.rmw16.sub_u"
- OpcodeAtomicI64Rmw32SubUName = "i64.atomic.rmw32.sub_u"
-
- OpcodeAtomicI32RmwAndName = "i32.atomic.rmw.and"
- OpcodeAtomicI64RmwAndName = "i64.atomic.rmw.and"
- OpcodeAtomicI32Rmw8AndUName = "i32.atomic.rmw8.and_u"
- OpcodeAtomicI32Rmw16AndUName = "i32.atomic.rmw16.and_u"
- OpcodeAtomicI64Rmw8AndUName = "i64.atomic.rmw8.and_u"
- OpcodeAtomicI64Rmw16AndUName = "i64.atomic.rmw16.and_u"
- OpcodeAtomicI64Rmw32AndUName = "i64.atomic.rmw32.and_u"
-
- OpcodeAtomicI32RmwOrName = "i32.atomic.rmw.or"
- OpcodeAtomicI64RmwOrName = "i64.atomic.rmw.or"
- OpcodeAtomicI32Rmw8OrUName = "i32.atomic.rmw8.or_u"
- OpcodeAtomicI32Rmw16OrUName = "i32.atomic.rmw16.or_u"
- OpcodeAtomicI64Rmw8OrUName = "i64.atomic.rmw8.or_u"
- OpcodeAtomicI64Rmw16OrUName = "i64.atomic.rmw16.or_u"
- OpcodeAtomicI64Rmw32OrUName = "i64.atomic.rmw32.or_u"
-
- OpcodeAtomicI32RmwXorName = "i32.atomic.rmw.xor"
- OpcodeAtomicI64RmwXorName = "i64.atomic.rmw.xor"
- OpcodeAtomicI32Rmw8XorUName = "i32.atomic.rmw8.xor_u"
- OpcodeAtomicI32Rmw16XorUName = "i32.atomic.rmw16.xor_u"
- OpcodeAtomicI64Rmw8XorUName = "i64.atomic.rmw8.xor_u"
- OpcodeAtomicI64Rmw16XorUName = "i64.atomic.rmw16.xor_u"
- OpcodeAtomicI64Rmw32XorUName = "i64.atomic.rmw32.xor_u"
-
- OpcodeAtomicI32RmwXchgName = "i32.atomic.rmw.xchg"
- OpcodeAtomicI64RmwXchgName = "i64.atomic.rmw.xchg"
- OpcodeAtomicI32Rmw8XchgUName = "i32.atomic.rmw8.xchg_u"
- OpcodeAtomicI32Rmw16XchgUName = "i32.atomic.rmw16.xchg_u"
- OpcodeAtomicI64Rmw8XchgUName = "i64.atomic.rmw8.xchg_u"
- OpcodeAtomicI64Rmw16XchgUName = "i64.atomic.rmw16.xchg_u"
- OpcodeAtomicI64Rmw32XchgUName = "i64.atomic.rmw32.xchg_u"
-
- OpcodeAtomicI32RmwCmpxchgName = "i32.atomic.rmw.cmpxchg"
- OpcodeAtomicI64RmwCmpxchgName = "i64.atomic.rmw.cmpxchg"
- OpcodeAtomicI32Rmw8CmpxchgUName = "i32.atomic.rmw8.cmpxchg_u"
- OpcodeAtomicI32Rmw16CmpxchgUName = "i32.atomic.rmw16.cmpxchg_u"
- OpcodeAtomicI64Rmw8CmpxchgUName = "i64.atomic.rmw8.cmpxchg_u"
- OpcodeAtomicI64Rmw16CmpxchgUName = "i64.atomic.rmw16.cmpxchg_u"
- OpcodeAtomicI64Rmw32CmpxchgUName = "i64.atomic.rmw32.cmpxchg_u"
-)
-
-var atomicInstructionName = map[OpcodeAtomic]string{
- OpcodeAtomicMemoryNotify: OpcodeAtomicMemoryNotifyName,
- OpcodeAtomicMemoryWait32: OpcodeAtomicMemoryWait32Name,
- OpcodeAtomicMemoryWait64: OpcodeAtomicMemoryWait64Name,
- OpcodeAtomicFence: OpcodeAtomicFenceName,
-
- OpcodeAtomicI32Load: OpcodeAtomicI32LoadName,
- OpcodeAtomicI64Load: OpcodeAtomicI64LoadName,
- OpcodeAtomicI32Load8U: OpcodeAtomicI32Load8UName,
- OpcodeAtomicI32Load16U: OpcodeAtomicI32Load16UName,
- OpcodeAtomicI64Load8U: OpcodeAtomicI64Load8UName,
- OpcodeAtomicI64Load16U: OpcodeAtomicI64Load16UName,
- OpcodeAtomicI64Load32U: OpcodeAtomicI64Load32UName,
- OpcodeAtomicI32Store: OpcodeAtomicI32StoreName,
- OpcodeAtomicI64Store: OpcodeAtomicI64StoreName,
- OpcodeAtomicI32Store8: OpcodeAtomicI32Store8Name,
- OpcodeAtomicI32Store16: OpcodeAtomicI32Store16Name,
- OpcodeAtomicI64Store8: OpcodeAtomicI64Store8Name,
- OpcodeAtomicI64Store16: OpcodeAtomicI64Store16Name,
- OpcodeAtomicI64Store32: OpcodeAtomicI64Store32Name,
-
- OpcodeAtomicI32RmwAdd: OpcodeAtomicI32RmwAddName,
- OpcodeAtomicI64RmwAdd: OpcodeAtomicI64RmwAddName,
- OpcodeAtomicI32Rmw8AddU: OpcodeAtomicI32Rmw8AddUName,
- OpcodeAtomicI32Rmw16AddU: OpcodeAtomicI32Rmw16AddUName,
- OpcodeAtomicI64Rmw8AddU: OpcodeAtomicI64Rmw8AddUName,
- OpcodeAtomicI64Rmw16AddU: OpcodeAtomicI64Rmw16AddUName,
- OpcodeAtomicI64Rmw32AddU: OpcodeAtomicI64Rmw32AddUName,
-
- OpcodeAtomicI32RmwSub: OpcodeAtomicI32RmwSubName,
- OpcodeAtomicI64RmwSub: OpcodeAtomicI64RmwSubName,
- OpcodeAtomicI32Rmw8SubU: OpcodeAtomicI32Rmw8SubUName,
- OpcodeAtomicI32Rmw16SubU: OpcodeAtomicI32Rmw16SubUName,
- OpcodeAtomicI64Rmw8SubU: OpcodeAtomicI64Rmw8SubUName,
- OpcodeAtomicI64Rmw16SubU: OpcodeAtomicI64Rmw16SubUName,
- OpcodeAtomicI64Rmw32SubU: OpcodeAtomicI64Rmw32SubUName,
-
- OpcodeAtomicI32RmwAnd: OpcodeAtomicI32RmwAndName,
- OpcodeAtomicI64RmwAnd: OpcodeAtomicI64RmwAndName,
- OpcodeAtomicI32Rmw8AndU: OpcodeAtomicI32Rmw8AndUName,
- OpcodeAtomicI32Rmw16AndU: OpcodeAtomicI32Rmw16AndUName,
- OpcodeAtomicI64Rmw8AndU: OpcodeAtomicI64Rmw8AndUName,
- OpcodeAtomicI64Rmw16AndU: OpcodeAtomicI64Rmw16AndUName,
- OpcodeAtomicI64Rmw32AndU: OpcodeAtomicI64Rmw32AndUName,
-
- OpcodeAtomicI32RmwOr: OpcodeAtomicI32RmwOrName,
- OpcodeAtomicI64RmwOr: OpcodeAtomicI64RmwOrName,
- OpcodeAtomicI32Rmw8OrU: OpcodeAtomicI32Rmw8OrUName,
- OpcodeAtomicI32Rmw16OrU: OpcodeAtomicI32Rmw16OrUName,
- OpcodeAtomicI64Rmw8OrU: OpcodeAtomicI64Rmw8OrUName,
- OpcodeAtomicI64Rmw16OrU: OpcodeAtomicI64Rmw16OrUName,
- OpcodeAtomicI64Rmw32OrU: OpcodeAtomicI64Rmw32OrUName,
-
- OpcodeAtomicI32RmwXor: OpcodeAtomicI32RmwXorName,
- OpcodeAtomicI64RmwXor: OpcodeAtomicI64RmwXorName,
- OpcodeAtomicI32Rmw8XorU: OpcodeAtomicI32Rmw8XorUName,
- OpcodeAtomicI32Rmw16XorU: OpcodeAtomicI32Rmw16XorUName,
- OpcodeAtomicI64Rmw8XorU: OpcodeAtomicI64Rmw8XorUName,
- OpcodeAtomicI64Rmw16XorU: OpcodeAtomicI64Rmw16XorUName,
- OpcodeAtomicI64Rmw32XorU: OpcodeAtomicI64Rmw32XorUName,
-
- OpcodeAtomicI32RmwXchg: OpcodeAtomicI32RmwXchgName,
- OpcodeAtomicI64RmwXchg: OpcodeAtomicI64RmwXchgName,
- OpcodeAtomicI32Rmw8XchgU: OpcodeAtomicI32Rmw8XchgUName,
- OpcodeAtomicI32Rmw16XchgU: OpcodeAtomicI32Rmw16XchgUName,
- OpcodeAtomicI64Rmw8XchgU: OpcodeAtomicI64Rmw8XchgUName,
- OpcodeAtomicI64Rmw16XchgU: OpcodeAtomicI64Rmw16XchgUName,
- OpcodeAtomicI64Rmw32XchgU: OpcodeAtomicI64Rmw32XchgUName,
-
- OpcodeAtomicI32RmwCmpxchg: OpcodeAtomicI32RmwCmpxchgName,
- OpcodeAtomicI64RmwCmpxchg: OpcodeAtomicI64RmwCmpxchgName,
- OpcodeAtomicI32Rmw8CmpxchgU: OpcodeAtomicI32Rmw8CmpxchgUName,
- OpcodeAtomicI32Rmw16CmpxchgU: OpcodeAtomicI32Rmw16CmpxchgUName,
- OpcodeAtomicI64Rmw8CmpxchgU: OpcodeAtomicI64Rmw8CmpxchgUName,
- OpcodeAtomicI64Rmw16CmpxchgU: OpcodeAtomicI64Rmw16CmpxchgUName,
- OpcodeAtomicI64Rmw32CmpxchgU: OpcodeAtomicI64Rmw32CmpxchgUName,
-}
-
-// AtomicInstructionName returns the instruction name corresponding to the atomic Opcode.
-func AtomicInstructionName(oc OpcodeAtomic) (ret string) {
- return atomicInstructionName[oc]
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go
deleted file mode 100644
index 9a1f0c6d1..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/memory.go
+++ /dev/null
@@ -1,476 +0,0 @@
-package wasm
-
-import (
- "container/list"
- "encoding/binary"
- "fmt"
- "math"
- "reflect"
- "sync"
- "sync/atomic"
- "time"
- "unsafe"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/experimental"
- "github.com/tetratelabs/wazero/internal/internalapi"
- "github.com/tetratelabs/wazero/internal/wasmruntime"
-)
-
-const (
- // MemoryPageSize is the unit of memory length in WebAssembly,
- // and is defined as 2^16 = 65536.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0
- MemoryPageSize = uint32(65536)
- // MemoryLimitPages is maximum number of pages defined (2^16).
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
- MemoryLimitPages = uint32(65536)
- // MemoryPageSizeInBits satisfies the relation: "1 << MemoryPageSizeInBits == MemoryPageSize".
- MemoryPageSizeInBits = 16
-)
-
-// compile-time check to ensure MemoryInstance implements api.Memory
-var _ api.Memory = &MemoryInstance{}
-
-type waiters struct {
- mux sync.Mutex
- l *list.List
-}
-
-// MemoryInstance represents a memory instance in a store, and implements api.Memory.
-//
-// Note: In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means the precise memory is always
-// wasm.Store Memories index zero: `store.Memories[0]`
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0.
-type MemoryInstance struct {
- internalapi.WazeroOnlyType
-
- Buffer []byte
- Min, Cap, Max uint32
- Shared bool
- // definition is known at compile time.
- definition api.MemoryDefinition
-
- // Mux is used in interpreter mode to prevent overlapping calls to atomic instructions,
- // introduced with WebAssembly threads proposal, and in compiler mode to make memory modifications
- // within Grow non-racy for the Go race detector.
- Mux sync.Mutex
-
- // waiters implements atomic wait and notify. It is implemented similarly to golang.org/x/sync/semaphore,
- // with a fixed weight of 1 and no spurious notifications.
- waiters sync.Map
-
- // ownerModuleEngine is the module engine that owns this memory instance.
- ownerModuleEngine ModuleEngine
-
- expBuffer experimental.LinearMemory
-}
-
-// NewMemoryInstance creates a new instance based on the parameters in the SectionIDMemory.
-func NewMemoryInstance(memSec *Memory, allocator experimental.MemoryAllocator, moduleEngine ModuleEngine) *MemoryInstance {
- minBytes := MemoryPagesToBytesNum(memSec.Min)
- capBytes := MemoryPagesToBytesNum(memSec.Cap)
- maxBytes := MemoryPagesToBytesNum(memSec.Max)
-
- var buffer []byte
- var expBuffer experimental.LinearMemory
- if allocator != nil {
- expBuffer = allocator.Allocate(capBytes, maxBytes)
- buffer = expBuffer.Reallocate(minBytes)
- _ = buffer[:minBytes] // Bounds check that the minimum was allocated.
- } else if memSec.IsShared {
- // Shared memory needs a fixed buffer, so allocate with the maximum size.
- //
- // The rationale as to why we can simply use make([]byte) to a fixed buffer is that Go's GC is non-relocating.
- // That is not a part of Go spec, but is well-known thing in Go community (wazero's compiler heavily relies on it!)
- // * https://github.com/go4org/unsafe-assume-no-moving-gc
- //
- // Also, allocating Max here isn't harmful as the Go runtime uses mmap for large allocations, therefore,
- // the memory buffer allocation here is virtual and doesn't consume physical memory until it's used.
- // * https://github.com/golang/go/blob/8121604559035734c9677d5281bbdac8b1c17a1e/src/runtime/malloc.go#L1059
- // * https://github.com/golang/go/blob/8121604559035734c9677d5281bbdac8b1c17a1e/src/runtime/malloc.go#L1165
- buffer = make([]byte, minBytes, maxBytes)
- } else {
- buffer = make([]byte, minBytes, capBytes)
- }
- return &MemoryInstance{
- Buffer: buffer,
- Min: memSec.Min,
- Cap: memoryBytesNumToPages(uint64(cap(buffer))),
- Max: memSec.Max,
- Shared: memSec.IsShared,
- expBuffer: expBuffer,
- ownerModuleEngine: moduleEngine,
- }
-}
-
-// Definition implements the same method as documented on api.Memory.
-func (m *MemoryInstance) Definition() api.MemoryDefinition {
- return m.definition
-}
-
-// Size implements the same method as documented on api.Memory.
-func (m *MemoryInstance) Size() uint32 {
- return uint32(len(m.Buffer))
-}
-
-// ReadByte implements the same method as documented on api.Memory.
-func (m *MemoryInstance) ReadByte(offset uint32) (byte, bool) {
- if !m.hasSize(offset, 1) {
- return 0, false
- }
- return m.Buffer[offset], true
-}
-
-// ReadUint16Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) ReadUint16Le(offset uint32) (uint16, bool) {
- if !m.hasSize(offset, 2) {
- return 0, false
- }
- return binary.LittleEndian.Uint16(m.Buffer[offset : offset+2]), true
-}
-
-// ReadUint32Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) ReadUint32Le(offset uint32) (uint32, bool) {
- return m.readUint32Le(offset)
-}
-
-// ReadFloat32Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) ReadFloat32Le(offset uint32) (float32, bool) {
- v, ok := m.readUint32Le(offset)
- if !ok {
- return 0, false
- }
- return math.Float32frombits(v), true
-}
-
-// ReadUint64Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) ReadUint64Le(offset uint32) (uint64, bool) {
- return m.readUint64Le(offset)
-}
-
-// ReadFloat64Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) ReadFloat64Le(offset uint32) (float64, bool) {
- v, ok := m.readUint64Le(offset)
- if !ok {
- return 0, false
- }
- return math.Float64frombits(v), true
-}
-
-// Read implements the same method as documented on api.Memory.
-func (m *MemoryInstance) Read(offset, byteCount uint32) ([]byte, bool) {
- if !m.hasSize(offset, uint64(byteCount)) {
- return nil, false
- }
- return m.Buffer[offset : offset+byteCount : offset+byteCount], true
-}
-
-// WriteByte implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteByte(offset uint32, v byte) bool {
- if !m.hasSize(offset, 1) {
- return false
- }
- m.Buffer[offset] = v
- return true
-}
-
-// WriteUint16Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteUint16Le(offset uint32, v uint16) bool {
- if !m.hasSize(offset, 2) {
- return false
- }
- binary.LittleEndian.PutUint16(m.Buffer[offset:], v)
- return true
-}
-
-// WriteUint32Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteUint32Le(offset, v uint32) bool {
- return m.writeUint32Le(offset, v)
-}
-
-// WriteFloat32Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteFloat32Le(offset uint32, v float32) bool {
- return m.writeUint32Le(offset, math.Float32bits(v))
-}
-
-// WriteUint64Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteUint64Le(offset uint32, v uint64) bool {
- return m.writeUint64Le(offset, v)
-}
-
-// WriteFloat64Le implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteFloat64Le(offset uint32, v float64) bool {
- return m.writeUint64Le(offset, math.Float64bits(v))
-}
-
-// Write implements the same method as documented on api.Memory.
-func (m *MemoryInstance) Write(offset uint32, val []byte) bool {
- if !m.hasSize(offset, uint64(len(val))) {
- return false
- }
- copy(m.Buffer[offset:], val)
- return true
-}
-
-// WriteString implements the same method as documented on api.Memory.
-func (m *MemoryInstance) WriteString(offset uint32, val string) bool {
- if !m.hasSize(offset, uint64(len(val))) {
- return false
- }
- copy(m.Buffer[offset:], val)
- return true
-}
-
-// MemoryPagesToBytesNum converts the given pages into the number of bytes contained in these pages.
-func MemoryPagesToBytesNum(pages uint32) (bytesNum uint64) {
- return uint64(pages) << MemoryPageSizeInBits
-}
-
-// Grow implements the same method as documented on api.Memory.
-func (m *MemoryInstance) Grow(delta uint32) (result uint32, ok bool) {
- if m.Shared {
- m.Mux.Lock()
- defer m.Mux.Unlock()
- }
-
- currentPages := m.Pages()
- if delta == 0 {
- return currentPages, true
- }
-
- newPages := currentPages + delta
- if newPages > m.Max || int32(delta) < 0 {
- return 0, false
- } else if m.expBuffer != nil {
- buffer := m.expBuffer.Reallocate(MemoryPagesToBytesNum(newPages))
- if buffer == nil {
- // Allocator failed to grow.
- return 0, false
- }
- if m.Shared {
- if unsafe.SliceData(buffer) != unsafe.SliceData(m.Buffer) {
- panic("shared memory cannot move, this is a bug in the memory allocator")
- }
- // We assume grow is called under a guest lock.
- // But the memory length is accessed elsewhere,
- // so use atomic to make the new length visible across threads.
- atomicStoreLengthAndCap(&m.Buffer, uintptr(len(buffer)), uintptr(cap(buffer)))
- m.Cap = memoryBytesNumToPages(uint64(cap(buffer)))
- } else {
- m.Buffer = buffer
- m.Cap = newPages
- }
- } else if newPages > m.Cap { // grow the memory.
- if m.Shared {
- panic("shared memory cannot be grown, this is a bug in wazero")
- }
- m.Buffer = append(m.Buffer, make([]byte, MemoryPagesToBytesNum(delta))...)
- m.Cap = newPages
- } else { // We already have the capacity we need.
- if m.Shared {
- // We assume grow is called under a guest lock.
- // But the memory length is accessed elsewhere,
- // so use atomic to make the new length visible across threads.
- atomicStoreLength(&m.Buffer, uintptr(MemoryPagesToBytesNum(newPages)))
- } else {
- m.Buffer = m.Buffer[:MemoryPagesToBytesNum(newPages)]
- }
- }
- m.ownerModuleEngine.MemoryGrown()
- return currentPages, true
-}
-
-// Pages implements the same method as documented on api.Memory.
-func (m *MemoryInstance) Pages() (result uint32) {
- return memoryBytesNumToPages(uint64(len(m.Buffer)))
-}
-
-// PagesToUnitOfBytes converts the pages to a human-readable form similar to what's specified. e.g. 1 -> "64Ki"
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0
-func PagesToUnitOfBytes(pages uint32) string {
- k := pages * 64
- if k < 1024 {
- return fmt.Sprintf("%d Ki", k)
- }
- m := k / 1024
- if m < 1024 {
- return fmt.Sprintf("%d Mi", m)
- }
- g := m / 1024
- if g < 1024 {
- return fmt.Sprintf("%d Gi", g)
- }
- return fmt.Sprintf("%d Ti", g/1024)
-}
-
-// Below are raw functions used to implement the api.Memory API:
-
-// Uses atomic write to update the length of a slice.
-func atomicStoreLengthAndCap(slice *[]byte, length uintptr, cap uintptr) {
- //nolint:staticcheck
- slicePtr := (*reflect.SliceHeader)(unsafe.Pointer(slice))
- capPtr := (*uintptr)(unsafe.Pointer(&slicePtr.Cap))
- atomic.StoreUintptr(capPtr, cap)
- lenPtr := (*uintptr)(unsafe.Pointer(&slicePtr.Len))
- atomic.StoreUintptr(lenPtr, length)
-}
-
-// Uses atomic write to update the length of a slice.
-func atomicStoreLength(slice *[]byte, length uintptr) {
- //nolint:staticcheck
- slicePtr := (*reflect.SliceHeader)(unsafe.Pointer(slice))
- lenPtr := (*uintptr)(unsafe.Pointer(&slicePtr.Len))
- atomic.StoreUintptr(lenPtr, length)
-}
-
-// memoryBytesNumToPages converts the given number of bytes into the number of pages.
-func memoryBytesNumToPages(bytesNum uint64) (pages uint32) {
- return uint32(bytesNum >> MemoryPageSizeInBits)
-}
-
-// hasSize returns true if Len is sufficient for byteCount at the given offset.
-//
-// Note: This is always fine, because memory can grow, but never shrink.
-func (m *MemoryInstance) hasSize(offset uint32, byteCount uint64) bool {
- return uint64(offset)+byteCount <= uint64(len(m.Buffer)) // uint64 prevents overflow on add
-}
-
-// readUint32Le implements ReadUint32Le without using a context. This is extracted as both ints and floats are stored in
-// memory as uint32le.
-func (m *MemoryInstance) readUint32Le(offset uint32) (uint32, bool) {
- if !m.hasSize(offset, 4) {
- return 0, false
- }
- return binary.LittleEndian.Uint32(m.Buffer[offset : offset+4]), true
-}
-
-// readUint64Le implements ReadUint64Le without using a context. This is extracted as both ints and floats are stored in
-// memory as uint64le.
-func (m *MemoryInstance) readUint64Le(offset uint32) (uint64, bool) {
- if !m.hasSize(offset, 8) {
- return 0, false
- }
- return binary.LittleEndian.Uint64(m.Buffer[offset : offset+8]), true
-}
-
-// writeUint32Le implements WriteUint32Le without using a context. This is extracted as both ints and floats are stored
-// in memory as uint32le.
-func (m *MemoryInstance) writeUint32Le(offset uint32, v uint32) bool {
- if !m.hasSize(offset, 4) {
- return false
- }
- binary.LittleEndian.PutUint32(m.Buffer[offset:], v)
- return true
-}
-
-// writeUint64Le implements WriteUint64Le without using a context. This is extracted as both ints and floats are stored
-// in memory as uint64le.
-func (m *MemoryInstance) writeUint64Le(offset uint32, v uint64) bool {
- if !m.hasSize(offset, 8) {
- return false
- }
- binary.LittleEndian.PutUint64(m.Buffer[offset:], v)
- return true
-}
-
-// Wait32 suspends the caller until the offset is notified by a different agent.
-func (m *MemoryInstance) Wait32(offset uint32, exp uint32, timeout int64, reader func(mem *MemoryInstance, offset uint32) uint32) uint64 {
- w := m.getWaiters(offset)
- w.mux.Lock()
-
- cur := reader(m, offset)
- if cur != exp {
- w.mux.Unlock()
- return 1
- }
-
- return m.wait(w, timeout)
-}
-
-// Wait64 suspends the caller until the offset is notified by a different agent.
-func (m *MemoryInstance) Wait64(offset uint32, exp uint64, timeout int64, reader func(mem *MemoryInstance, offset uint32) uint64) uint64 {
- w := m.getWaiters(offset)
- w.mux.Lock()
-
- cur := reader(m, offset)
- if cur != exp {
- w.mux.Unlock()
- return 1
- }
-
- return m.wait(w, timeout)
-}
-
-func (m *MemoryInstance) wait(w *waiters, timeout int64) uint64 {
- if w.l == nil {
- w.l = list.New()
- }
-
- // The specification requires a trap if the number of existing waiters + 1 == 2^32, so we add a check here.
- // In practice, it is unlikely the application would ever accumulate such a large number of waiters as it
- // indicates several GB of RAM used just for the list of waiters.
- // https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#wait
- if uint64(w.l.Len()+1) == 1<<32 {
- w.mux.Unlock()
- panic(wasmruntime.ErrRuntimeTooManyWaiters)
- }
-
- ready := make(chan struct{})
- elem := w.l.PushBack(ready)
- w.mux.Unlock()
-
- if timeout < 0 {
- <-ready
- return 0
- } else {
- select {
- case <-ready:
- return 0
- case <-time.After(time.Duration(timeout)):
- // While we could see if the channel completed by now and ignore the timeout, similar to x/sync/semaphore,
- // the Wasm spec doesn't specify this behavior, so we keep things simple by prioritizing the timeout.
- w.mux.Lock()
- w.l.Remove(elem)
- w.mux.Unlock()
- return 2
- }
- }
-}
-
-func (m *MemoryInstance) getWaiters(offset uint32) *waiters {
- wAny, ok := m.waiters.Load(offset)
- if !ok {
- // The first time an address is waited on, simultaneous waits will cause extra allocations.
- // Further operations will be loaded above, which is also the general pattern of usage with
- // mutexes.
- wAny, _ = m.waiters.LoadOrStore(offset, &waiters{})
- }
-
- return wAny.(*waiters)
-}
-
-// Notify wakes up at most count waiters at the given offset.
-func (m *MemoryInstance) Notify(offset uint32, count uint32) uint32 {
- wAny, ok := m.waiters.Load(offset)
- if !ok {
- return 0
- }
- w := wAny.(*waiters)
-
- w.mux.Lock()
- defer w.mux.Unlock()
- if w.l == nil {
- return 0
- }
-
- res := uint32(0)
- for num := w.l.Len(); num > 0 && res < count; num = w.l.Len() {
- w := w.l.Remove(w.l.Front()).(chan struct{})
- close(w)
- res++
- }
-
- return res
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go
deleted file mode 100644
index 03d6fd303..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/memory_definition.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package wasm
-
-import (
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/internalapi"
-)
-
-// ImportedMemories implements the same method as documented on wazero.CompiledModule.
-func (m *Module) ImportedMemories() (ret []api.MemoryDefinition) {
- for i := range m.MemoryDefinitionSection {
- d := &m.MemoryDefinitionSection[i]
- if d.importDesc != nil {
- ret = append(ret, d)
- }
- }
- return
-}
-
-// ExportedMemories implements the same method as documented on wazero.CompiledModule.
-func (m *Module) ExportedMemories() map[string]api.MemoryDefinition {
- ret := map[string]api.MemoryDefinition{}
- for i := range m.MemoryDefinitionSection {
- d := &m.MemoryDefinitionSection[i]
- for _, e := range d.exportNames {
- ret[e] = d
- }
- }
- return ret
-}
-
-// BuildMemoryDefinitions generates memory metadata that can be parsed from
-// the module. This must be called after all validation.
-//
-// Note: This is exported for wazero.Runtime `CompileModule`.
-func (m *Module) BuildMemoryDefinitions() {
- var moduleName string
- if m.NameSection != nil {
- moduleName = m.NameSection.ModuleName
- }
-
- memoryCount := m.ImportMemoryCount
- if m.MemorySection != nil {
- memoryCount++
- }
-
- if memoryCount == 0 {
- return
- }
-
- m.MemoryDefinitionSection = make([]MemoryDefinition, 0, memoryCount)
- importMemIdx := Index(0)
- for i := range m.ImportSection {
- imp := &m.ImportSection[i]
- if imp.Type != ExternTypeMemory {
- continue
- }
-
- m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, MemoryDefinition{
- importDesc: &[2]string{imp.Module, imp.Name},
- index: importMemIdx,
- memory: imp.DescMem,
- })
- importMemIdx++
- }
-
- if m.MemorySection != nil {
- m.MemoryDefinitionSection = append(m.MemoryDefinitionSection, MemoryDefinition{
- index: importMemIdx,
- memory: m.MemorySection,
- })
- }
-
- for i := range m.MemoryDefinitionSection {
- d := &m.MemoryDefinitionSection[i]
- d.moduleName = moduleName
- for i := range m.ExportSection {
- e := &m.ExportSection[i]
- if e.Type == ExternTypeMemory && e.Index == d.index {
- d.exportNames = append(d.exportNames, e.Name)
- }
- }
- }
-}
-
-// MemoryDefinition implements api.MemoryDefinition
-type MemoryDefinition struct {
- internalapi.WazeroOnlyType
- moduleName string
- index Index
- importDesc *[2]string
- exportNames []string
- memory *Memory
-}
-
-// ModuleName implements the same method as documented on api.MemoryDefinition.
-func (f *MemoryDefinition) ModuleName() string {
- return f.moduleName
-}
-
-// Index implements the same method as documented on api.MemoryDefinition.
-func (f *MemoryDefinition) Index() uint32 {
- return f.index
-}
-
-// Import implements the same method as documented on api.MemoryDefinition.
-func (f *MemoryDefinition) Import() (moduleName, name string, isImport bool) {
- if importDesc := f.importDesc; importDesc != nil {
- moduleName, name, isImport = importDesc[0], importDesc[1], true
- }
- return
-}
-
-// ExportNames implements the same method as documented on api.MemoryDefinition.
-func (f *MemoryDefinition) ExportNames() []string {
- return f.exportNames
-}
-
-// Min implements the same method as documented on api.MemoryDefinition.
-func (f *MemoryDefinition) Min() uint32 {
- return f.memory.Min
-}
-
-// Max implements the same method as documented on api.MemoryDefinition.
-func (f *MemoryDefinition) Max() (max uint32, encoded bool) {
- max = f.memory.Max
- encoded = f.memory.IsMaxEncoded
- return
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/module.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/module.go
deleted file mode 100644
index 8369ad9ed..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/module.go
+++ /dev/null
@@ -1,1078 +0,0 @@
-package wasm
-
-import (
- "bytes"
- "crypto/sha256"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "sort"
- "strings"
- "sync"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/experimental"
- "github.com/tetratelabs/wazero/internal/ieee754"
- "github.com/tetratelabs/wazero/internal/leb128"
- "github.com/tetratelabs/wazero/internal/wasmdebug"
-)
-
-// Module is a WebAssembly binary representation.
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#modules%E2%91%A8
-//
-// Differences from the specification:
-// * NameSection is the only key ("name") decoded from the SectionIDCustom.
-// * ExportSection is represented as a map for lookup convenience.
-// * Code.GoFunc is contains any go `func`. It may be present when Code.Body is not.
-type Module struct {
- // TypeSection contains the unique FunctionType of functions imported or defined in this module.
- //
- // Note: Currently, there is no type ambiguity in the index as WebAssembly 1.0 only defines function type.
- // In the future, other types may be introduced to support CoreFeatures such as module linking.
- //
- // Note: In the Binary Format, this is SectionIDType.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#types%E2%91%A0%E2%91%A0
- TypeSection []FunctionType
-
- // ImportSection contains imported functions, tables, memories or globals required for instantiation
- // (Store.Instantiate).
- //
- // Note: there are no unique constraints relating to the two-level namespace of Import.Module and Import.Name.
- //
- // Note: In the Binary Format, this is SectionIDImport.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#import-section%E2%91%A0
- ImportSection []Import
- // ImportFunctionCount ImportGlobalCount ImportMemoryCount, and ImportTableCount are
- // the cached import count per ExternType set during decoding.
- ImportFunctionCount,
- ImportGlobalCount,
- ImportMemoryCount,
- ImportTableCount Index
- // ImportPerModule maps a module name to the list of Import to be imported from the module.
- // This is used to do fast import resolution during instantiation.
- ImportPerModule map[string][]*Import
-
- // FunctionSection contains the index in TypeSection of each function defined in this module.
- //
- // Note: The function Index space begins with imported functions and ends with those defined in this module.
- // For example, if there are two imported functions and one defined in this module, the function Index 3 is defined
- // in this module at FunctionSection[0].
- //
- // Note: FunctionSection is index correlated with the CodeSection. If given the same position, e.g. 2, a function
- // type is at TypeSection[FunctionSection[2]], while its locals and body are at CodeSection[2].
- //
- // Note: In the Binary Format, this is SectionIDFunction.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#function-section%E2%91%A0
- FunctionSection []Index
-
- // TableSection contains each table defined in this module.
- //
- // Note: The table Index space begins with imported tables and ends with those defined in this module.
- // For example, if there are two imported tables and one defined in this module, the table Index 3 is defined in
- // this module at TableSection[0].
- //
- // Note: Version 1.0 (20191205) of the WebAssembly spec allows at most one table definition per module, so the
- // length of the TableSection can be zero or one, and can only be one if there is no imported table.
- //
- // Note: In the Binary Format, this is SectionIDTable.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#table-section%E2%91%A0
- TableSection []Table
-
- // MemorySection contains each memory defined in this module.
- //
- // Note: The memory Index space begins with imported memories and ends with those defined in this module.
- // For example, if there are two imported memories and one defined in this module, the memory Index 3 is defined in
- // this module at TableSection[0].
- //
- // Note: Version 1.0 (20191205) of the WebAssembly spec allows at most one memory definition per module, so the
- // length of the MemorySection can be zero or one, and can only be one if there is no imported memory.
- //
- // Note: In the Binary Format, this is SectionIDMemory.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-section%E2%91%A0
- MemorySection *Memory
-
- // GlobalSection contains each global defined in this module.
- //
- // Global indexes are offset by any imported globals because the global index begins with imports, followed by
- // ones defined in this module. For example, if there are two imported globals and three defined in this module, the
- // global at index 3 is defined in this module at GlobalSection[0].
- //
- // Note: In the Binary Format, this is SectionIDGlobal.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#global-section%E2%91%A0
- GlobalSection []Global
-
- // ExportSection contains each export defined in this module.
- //
- // Note: In the Binary Format, this is SectionIDExport.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A0
- ExportSection []Export
- // Exports maps a name to Export, and is convenient for fast look up of exported instances at runtime.
- // Each item of this map points to an element of ExportSection.
- Exports map[string]*Export
-
- // StartSection is the index of a function to call before returning from Store.Instantiate.
- //
- // Note: The index here is not the position in the FunctionSection, rather in the function index, which
- // begins with imported functions.
- //
- // Note: In the Binary Format, this is SectionIDStart.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#start-section%E2%91%A0
- StartSection *Index
-
- // Note: In the Binary Format, this is SectionIDElement.
- ElementSection []ElementSegment
-
- // CodeSection is index-correlated with FunctionSection and contains each
- // function's locals and body.
- //
- // When present, the HostFunctionSection of the same index must be nil.
- //
- // Note: In the Binary Format, this is SectionIDCode.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#code-section%E2%91%A0
- CodeSection []Code
-
- // Note: In the Binary Format, this is SectionIDData.
- DataSection []DataSegment
-
- // NameSection is set when the SectionIDCustom "name" was successfully decoded from the binary format.
- //
- // Note: This is the only SectionIDCustom defined in the WebAssembly 1.0 (20191205) Binary Format.
- // Others are skipped as they are not used in wazero.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0
- NameSection *NameSection
-
- // CustomSections are set when the SectionIDCustom other than "name" were successfully decoded from the binary format.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0
- CustomSections []*CustomSection
-
- // DataCountSection is the optional section and holds the number of data segments in the data section.
- //
- // Note: This may exist in WebAssembly 2.0 or WebAssembly 1.0 with CoreFeatureBulkMemoryOperations.
- // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-count-section
- // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions
- DataCountSection *uint32
-
- // ID is the sha256 value of the source wasm plus the configurations which affect the runtime representation of
- // Wasm binary. This is only used for caching.
- ID ModuleID
-
- // IsHostModule true if this is the host module, false otherwise.
- IsHostModule bool
-
- // functionDefinitionSectionInitOnce guards FunctionDefinitionSection so that it is initialized exactly once.
- functionDefinitionSectionInitOnce sync.Once
-
- // FunctionDefinitionSection is a wazero-specific section.
- FunctionDefinitionSection []FunctionDefinition
-
- // MemoryDefinitionSection is a wazero-specific section.
- MemoryDefinitionSection []MemoryDefinition
-
- // DWARFLines is used to emit DWARF based stack trace. This is created from the multiple custom sections
- // as described in https://yurydelendik.github.io/webassembly-dwarf/, though it is not specified in the Wasm
- // specification: https://github.com/WebAssembly/debugging/issues/1
- DWARFLines *wasmdebug.DWARFLines
-}
-
-// ModuleID represents sha256 hash value uniquely assigned to Module.
-type ModuleID = [sha256.Size]byte
-
-// The wazero specific limitation described at RATIONALE.md.
-// TL;DR; We multiply by 8 (to get offsets in bytes) and the multiplication result must be less than 32bit max
-const (
- MaximumGlobals = uint32(1 << 27)
- MaximumFunctionIndex = uint32(1 << 27)
- MaximumTableIndex = uint32(1 << 27)
-)
-
-// AssignModuleID calculates a sha256 checksum on `wasm` and other args, and set Module.ID to the result.
-// See the doc on Module.ID on what it's used for.
-func (m *Module) AssignModuleID(wasm []byte, listeners []experimental.FunctionListener, withEnsureTermination bool) {
- h := sha256.New()
- h.Write(wasm)
- // Use the pre-allocated space backed by m.ID below.
-
- // Write the existence of listeners to the checksum per function.
- for i, l := range listeners {
- binary.LittleEndian.PutUint32(m.ID[:], uint32(i))
- m.ID[4] = boolToByte(l != nil)
- h.Write(m.ID[:5])
- }
- // Write the flag of ensureTermination to the checksum.
- m.ID[0] = boolToByte(withEnsureTermination)
- h.Write(m.ID[:1])
- // Get checksum by passing the slice underlying m.ID.
- h.Sum(m.ID[:0])
-}
-
-func boolToByte(b bool) (ret byte) {
- if b {
- ret = 1
- }
- return
-}
-
-// typeOfFunction returns the wasm.FunctionType for the given function space index or nil.
-func (m *Module) typeOfFunction(funcIdx Index) *FunctionType {
- typeSectionLength, importedFunctionCount := uint32(len(m.TypeSection)), m.ImportFunctionCount
- if funcIdx < importedFunctionCount {
- // Imports are not exclusively functions. This is the current function index in the loop.
- cur := Index(0)
- for i := range m.ImportSection {
- imp := &m.ImportSection[i]
- if imp.Type != ExternTypeFunc {
- continue
- }
- if funcIdx == cur {
- if imp.DescFunc >= typeSectionLength {
- return nil
- }
- return &m.TypeSection[imp.DescFunc]
- }
- cur++
- }
- }
-
- funcSectionIdx := funcIdx - m.ImportFunctionCount
- if funcSectionIdx >= uint32(len(m.FunctionSection)) {
- return nil
- }
- typeIdx := m.FunctionSection[funcSectionIdx]
- if typeIdx >= typeSectionLength {
- return nil
- }
- return &m.TypeSection[typeIdx]
-}
-
-func (m *Module) Validate(enabledFeatures api.CoreFeatures) error {
- for i := range m.TypeSection {
- tp := &m.TypeSection[i]
- tp.CacheNumInUint64()
- }
-
- if err := m.validateStartSection(); err != nil {
- return err
- }
-
- functions, globals, memory, tables, err := m.AllDeclarations()
- if err != nil {
- return err
- }
-
- if err = m.validateImports(enabledFeatures); err != nil {
- return err
- }
-
- if err = m.validateGlobals(globals, uint32(len(functions)), MaximumGlobals); err != nil {
- return err
- }
-
- if err = m.validateMemory(memory, globals, enabledFeatures); err != nil {
- return err
- }
-
- if err = m.validateExports(enabledFeatures, functions, globals, memory, tables); err != nil {
- return err
- }
-
- if m.CodeSection != nil {
- if err = m.validateFunctions(enabledFeatures, functions, globals, memory, tables, MaximumFunctionIndex); err != nil {
- return err
- }
- } // No need to validate host functions as NewHostModule validates
-
- if err = m.validateTable(enabledFeatures, tables, MaximumTableIndex); err != nil {
- return err
- }
-
- if err = m.validateDataCountSection(); err != nil {
- return err
- }
- return nil
-}
-
-func (m *Module) validateStartSection() error {
- // Check the start function is valid.
- // TODO: this should be verified during decode so that errors have the correct source positions
- if m.StartSection != nil {
- startIndex := *m.StartSection
- ft := m.typeOfFunction(startIndex)
- if ft == nil { // TODO: move this check to decoder so that a module can never be decoded invalidly
- return fmt.Errorf("invalid start function: func[%d] has an invalid type", startIndex)
- }
- if len(ft.Params) > 0 || len(ft.Results) > 0 {
- return fmt.Errorf("invalid start function: func[%d] must have an empty (nullary) signature: %s", startIndex, ft)
- }
- }
- return nil
-}
-
-func (m *Module) validateGlobals(globals []GlobalType, numFuncts, maxGlobals uint32) error {
- if uint32(len(globals)) > maxGlobals {
- return fmt.Errorf("too many globals in a module")
- }
-
- // Global initialization constant expression can only reference the imported globals.
- // See the note on https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#constant-expressions%E2%91%A0
- importedGlobals := globals[:m.ImportGlobalCount]
- for i := range m.GlobalSection {
- g := &m.GlobalSection[i]
- if err := validateConstExpression(importedGlobals, numFuncts, &g.Init, g.Type.ValType); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (m *Module) validateFunctions(enabledFeatures api.CoreFeatures, functions []Index, globals []GlobalType, memory *Memory, tables []Table, maximumFunctionIndex uint32) error {
- if uint32(len(functions)) > maximumFunctionIndex {
- return fmt.Errorf("too many functions (%d) in a module", len(functions))
- }
-
- functionCount := m.SectionElementCount(SectionIDFunction)
- codeCount := m.SectionElementCount(SectionIDCode)
- if functionCount == 0 && codeCount == 0 {
- return nil
- }
-
- typeCount := m.SectionElementCount(SectionIDType)
- if codeCount != functionCount {
- return fmt.Errorf("code count (%d) != function count (%d)", codeCount, functionCount)
- }
-
- declaredFuncIndexes, err := m.declaredFunctionIndexes()
- if err != nil {
- return err
- }
-
- // Create bytes.Reader once as it causes allocation, and
- // we frequently need it (e.g. on every If instruction).
- br := bytes.NewReader(nil)
- // Also, we reuse the stacks across multiple function validations to reduce allocations.
- vs := &stacks{}
- for idx, typeIndex := range m.FunctionSection {
- if typeIndex >= typeCount {
- return fmt.Errorf("invalid %s: type section index %d out of range", m.funcDesc(SectionIDFunction, Index(idx)), typeIndex)
- }
- c := &m.CodeSection[idx]
- if c.GoFunc != nil {
- continue
- }
- if err = m.validateFunction(vs, enabledFeatures, Index(idx), functions, globals, memory, tables, declaredFuncIndexes, br); err != nil {
- return fmt.Errorf("invalid %s: %w", m.funcDesc(SectionIDFunction, Index(idx)), err)
- }
- }
- return nil
-}
-
-// declaredFunctionIndexes returns a set of function indexes that can be used as an immediate for OpcodeRefFunc instruction.
-//
-// The criteria for which function indexes can be available for that instruction is vague in the spec:
-//
-// - "References: the list of function indices that occur in the module outside functions and can hence be used to form references inside them."
-// - https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/valid/conventions.html#contexts
-// - "Ref is the set funcidx(module with functions=ε, start=ε) , i.e., the set of function indices occurring in the module, except in its functions or start function."
-// - https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/valid/modules.html#valid-module
-//
-// To clarify, we reverse-engineer logic required to pass the WebAssembly Core specification 2.0 test suite:
-// https://github.com/WebAssembly/spec/blob/d39195773112a22b245ffbe864bab6d1182ccb06/test/core/ref_func.wast#L78-L115
-//
-// To summarize, the function indexes OpcodeRefFunc can refer include:
-// - existing in an element section regardless of its mode (active, passive, declarative).
-// - defined as globals whose value type is ValueRefFunc.
-// - used as an exported function.
-//
-// See https://github.com/WebAssembly/reference-types/issues/31
-// See https://github.com/WebAssembly/reference-types/issues/76
-func (m *Module) declaredFunctionIndexes() (ret map[Index]struct{}, err error) {
- ret = map[uint32]struct{}{}
-
- for i := range m.ExportSection {
- exp := &m.ExportSection[i]
- if exp.Type == ExternTypeFunc {
- ret[exp.Index] = struct{}{}
- }
- }
-
- for i := range m.GlobalSection {
- g := &m.GlobalSection[i]
- if g.Init.Opcode == OpcodeRefFunc {
- var index uint32
- index, _, err = leb128.LoadUint32(g.Init.Data)
- if err != nil {
- err = fmt.Errorf("%s[%d] failed to initialize: %w", SectionIDName(SectionIDGlobal), i, err)
- return
- }
- ret[index] = struct{}{}
- }
- }
-
- for i := range m.ElementSection {
- elem := &m.ElementSection[i]
- for _, index := range elem.Init {
- if index != ElementInitNullReference {
- ret[index] = struct{}{}
- }
- }
- }
- return
-}
-
-func (m *Module) funcDesc(sectionID SectionID, sectionIndex Index) string {
- // Try to improve the error message by collecting any exports:
- var exportNames []string
- funcIdx := sectionIndex + m.ImportFunctionCount
- for i := range m.ExportSection {
- exp := &m.ExportSection[i]
- if exp.Index == funcIdx && exp.Type == ExternTypeFunc {
- exportNames = append(exportNames, fmt.Sprintf("%q", exp.Name))
- }
- }
- sectionIDName := SectionIDName(sectionID)
- if exportNames == nil {
- return fmt.Sprintf("%s[%d]", sectionIDName, sectionIndex)
- }
- sort.Strings(exportNames) // go map keys do not iterate consistently
- return fmt.Sprintf("%s[%d] export[%s]", sectionIDName, sectionIndex, strings.Join(exportNames, ","))
-}
-
-func (m *Module) validateMemory(memory *Memory, globals []GlobalType, _ api.CoreFeatures) error {
- var activeElementCount int
- for i := range m.DataSection {
- d := &m.DataSection[i]
- if !d.IsPassive() {
- activeElementCount++
- }
- }
- if activeElementCount > 0 && memory == nil {
- return fmt.Errorf("unknown memory")
- }
-
- // Constant expression can only reference imported globals.
- // https://github.com/WebAssembly/spec/blob/5900d839f38641989a9d8df2df4aee0513365d39/test/core/data.wast#L84-L91
- importedGlobals := globals[:m.ImportGlobalCount]
- for i := range m.DataSection {
- d := &m.DataSection[i]
- if !d.IsPassive() {
- if err := validateConstExpression(importedGlobals, 0, &d.OffsetExpression, ValueTypeI32); err != nil {
- return fmt.Errorf("calculate offset: %w", err)
- }
- }
- }
- return nil
-}
-
-func (m *Module) validateImports(enabledFeatures api.CoreFeatures) error {
- for i := range m.ImportSection {
- imp := &m.ImportSection[i]
- if imp.Module == "" {
- return fmt.Errorf("import[%d] has an empty module name", i)
- }
- switch imp.Type {
- case ExternTypeFunc:
- if int(imp.DescFunc) >= len(m.TypeSection) {
- return fmt.Errorf("invalid import[%q.%q] function: type index out of range", imp.Module, imp.Name)
- }
- case ExternTypeGlobal:
- if !imp.DescGlobal.Mutable {
- continue
- }
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureMutableGlobal); err != nil {
- return fmt.Errorf("invalid import[%q.%q] global: %w", imp.Module, imp.Name, err)
- }
- }
- }
- return nil
-}
-
-func (m *Module) validateExports(enabledFeatures api.CoreFeatures, functions []Index, globals []GlobalType, memory *Memory, tables []Table) error {
- for i := range m.ExportSection {
- exp := &m.ExportSection[i]
- index := exp.Index
- switch exp.Type {
- case ExternTypeFunc:
- if index >= uint32(len(functions)) {
- return fmt.Errorf("unknown function for export[%q]", exp.Name)
- }
- case ExternTypeGlobal:
- if index >= uint32(len(globals)) {
- return fmt.Errorf("unknown global for export[%q]", exp.Name)
- }
- if !globals[index].Mutable {
- continue
- }
- if err := enabledFeatures.RequireEnabled(api.CoreFeatureMutableGlobal); err != nil {
- return fmt.Errorf("invalid export[%q] global[%d]: %w", exp.Name, index, err)
- }
- case ExternTypeMemory:
- if index > 0 || memory == nil {
- return fmt.Errorf("memory for export[%q] out of range", exp.Name)
- }
- case ExternTypeTable:
- if index >= uint32(len(tables)) {
- return fmt.Errorf("table for export[%q] out of range", exp.Name)
- }
- }
- }
- return nil
-}
-
-func validateConstExpression(globals []GlobalType, numFuncs uint32, expr *ConstantExpression, expectedType ValueType) (err error) {
- var actualType ValueType
- switch expr.Opcode {
- case OpcodeI32Const:
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- _, _, err = leb128.LoadInt32(expr.Data)
- if err != nil {
- return fmt.Errorf("read i32: %w", err)
- }
- actualType = ValueTypeI32
- case OpcodeI64Const:
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- _, _, err = leb128.LoadInt64(expr.Data)
- if err != nil {
- return fmt.Errorf("read i64: %w", err)
- }
- actualType = ValueTypeI64
- case OpcodeF32Const:
- _, err = ieee754.DecodeFloat32(expr.Data)
- if err != nil {
- return fmt.Errorf("read f32: %w", err)
- }
- actualType = ValueTypeF32
- case OpcodeF64Const:
- _, err = ieee754.DecodeFloat64(expr.Data)
- if err != nil {
- return fmt.Errorf("read f64: %w", err)
- }
- actualType = ValueTypeF64
- case OpcodeGlobalGet:
- id, _, err := leb128.LoadUint32(expr.Data)
- if err != nil {
- return fmt.Errorf("read index of global: %w", err)
- }
- if uint32(len(globals)) <= id {
- return fmt.Errorf("global index out of range")
- }
- actualType = globals[id].ValType
- case OpcodeRefNull:
- if len(expr.Data) == 0 {
- return fmt.Errorf("read reference type for ref.null: %w", io.ErrShortBuffer)
- }
- reftype := expr.Data[0]
- if reftype != RefTypeFuncref && reftype != RefTypeExternref {
- return fmt.Errorf("invalid type for ref.null: 0x%x", reftype)
- }
- actualType = reftype
- case OpcodeRefFunc:
- index, _, err := leb128.LoadUint32(expr.Data)
- if err != nil {
- return fmt.Errorf("read i32: %w", err)
- } else if index >= numFuncs {
- return fmt.Errorf("ref.func index out of range [%d] with length %d", index, numFuncs-1)
- }
- actualType = ValueTypeFuncref
- case OpcodeVecV128Const:
- if len(expr.Data) != 16 {
- return fmt.Errorf("%s needs 16 bytes but was %d bytes", OpcodeVecV128ConstName, len(expr.Data))
- }
- actualType = ValueTypeV128
- default:
- return fmt.Errorf("invalid opcode for const expression: 0x%x", expr.Opcode)
- }
-
- if actualType != expectedType {
- return fmt.Errorf("const expression type mismatch expected %s but got %s",
- ValueTypeName(expectedType), ValueTypeName(actualType))
- }
- return nil
-}
-
-func (m *Module) validateDataCountSection() (err error) {
- if m.DataCountSection != nil && int(*m.DataCountSection) != len(m.DataSection) {
- err = fmt.Errorf("data count section (%d) doesn't match the length of data section (%d)",
- *m.DataCountSection, len(m.DataSection))
- }
- return
-}
-
-func (m *ModuleInstance) buildGlobals(module *Module, funcRefResolver func(funcIndex Index) Reference) {
- importedGlobals := m.Globals[:module.ImportGlobalCount]
-
- me := m.Engine
- engineOwnGlobal := me.OwnsGlobals()
- for i := Index(0); i < Index(len(module.GlobalSection)); i++ {
- gs := &module.GlobalSection[i]
- g := &GlobalInstance{}
- if engineOwnGlobal {
- g.Me = me
- g.Index = i + module.ImportGlobalCount
- }
- m.Globals[i+module.ImportGlobalCount] = g
- g.Type = gs.Type
- g.initialize(importedGlobals, &gs.Init, funcRefResolver)
- }
-}
-
-func paramNames(localNames IndirectNameMap, funcIdx uint32, paramLen int) []string {
- for i := range localNames {
- nm := &localNames[i]
- // Only build parameter names if we have one for each.
- if nm.Index != funcIdx || len(nm.NameMap) < paramLen {
- continue
- }
-
- ret := make([]string, paramLen)
- for j := range nm.NameMap {
- p := &nm.NameMap[j]
- if int(p.Index) < paramLen {
- ret[p.Index] = p.Name
- }
- }
- return ret
- }
- return nil
-}
-
-func (m *ModuleInstance) buildMemory(module *Module, allocator experimental.MemoryAllocator) {
- memSec := module.MemorySection
- if memSec != nil {
- m.MemoryInstance = NewMemoryInstance(memSec, allocator, m.Engine)
- m.MemoryInstance.definition = &module.MemoryDefinitionSection[0]
- }
-}
-
-// Index is the offset in an index, not necessarily an absolute position in a Module section. This is because
-// indexs are often preceded by a corresponding type in the Module.ImportSection.
-//
-// For example, the function index starts with any ExternTypeFunc in the Module.ImportSection followed by
-// the Module.FunctionSection
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-index
-type Index = uint32
-
-// FunctionType is a possibly empty function signature.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#function-types%E2%91%A0
-type FunctionType struct {
- // Params are the possibly empty sequence of value types accepted by a function with this signature.
- Params []ValueType
-
- // Results are the possibly empty sequence of value types returned by a function with this signature.
- //
- // Note: In WebAssembly 1.0 (20191205), there can be at most one result.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#result-types%E2%91%A0
- Results []ValueType
-
- // string is cached as it is used both for String and key
- string string
-
- // ParamNumInUint64 is the number of uint64 values requires to represent the Wasm param type.
- ParamNumInUint64 int
-
- // ResultsNumInUint64 is the number of uint64 values requires to represent the Wasm result type.
- ResultNumInUint64 int
-}
-
-func (f *FunctionType) CacheNumInUint64() {
- if f.ParamNumInUint64 == 0 {
- for _, tp := range f.Params {
- f.ParamNumInUint64++
- if tp == ValueTypeV128 {
- f.ParamNumInUint64++
- }
- }
- }
-
- if f.ResultNumInUint64 == 0 {
- for _, tp := range f.Results {
- f.ResultNumInUint64++
- if tp == ValueTypeV128 {
- f.ResultNumInUint64++
- }
- }
- }
-}
-
-// EqualsSignature returns true if the function type has the same parameters and results.
-func (f *FunctionType) EqualsSignature(params []ValueType, results []ValueType) bool {
- return bytes.Equal(f.Params, params) && bytes.Equal(f.Results, results)
-}
-
-// key gets or generates the key for Store.typeIDs. e.g. "i32_v" for one i32 parameter and no (void) result.
-func (f *FunctionType) key() string {
- if f.string != "" {
- return f.string
- }
- var ret string
- for _, b := range f.Params {
- ret += ValueTypeName(b)
- }
- if len(f.Params) == 0 {
- ret += "v_"
- } else {
- ret += "_"
- }
- for _, b := range f.Results {
- ret += ValueTypeName(b)
- }
- if len(f.Results) == 0 {
- ret += "v"
- }
- f.string = ret
- return ret
-}
-
-// String implements fmt.Stringer.
-func (f *FunctionType) String() string {
- return f.key()
-}
-
-// Import is the binary representation of an import indicated by Type
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-import
-type Import struct {
- Type ExternType
- // Module is the possibly empty primary namespace of this import
- Module string
- // Module is the possibly empty secondary namespace of this import
- Name string
- // DescFunc is the index in Module.TypeSection when Type equals ExternTypeFunc
- DescFunc Index
- // DescTable is the inlined Table when Type equals ExternTypeTable
- DescTable Table
- // DescMem is the inlined Memory when Type equals ExternTypeMemory
- DescMem *Memory
- // DescGlobal is the inlined GlobalType when Type equals ExternTypeGlobal
- DescGlobal GlobalType
- // IndexPerType has the index of this import per ExternType.
- IndexPerType Index
-}
-
-// Memory describes the limits of pages (64KB) in a memory.
-type Memory struct {
- Min, Cap, Max uint32
- // IsMaxEncoded true if the Max is encoded in the original binary.
- IsMaxEncoded bool
- // IsShared true if the memory is shared for access from multiple agents.
- IsShared bool
-}
-
-// Validate ensures values assigned to Min, Cap and Max are within valid thresholds.
-func (m *Memory) Validate(memoryLimitPages uint32) error {
- min, capacity, max := m.Min, m.Cap, m.Max
-
- if max > memoryLimitPages {
- return fmt.Errorf("max %d pages (%s) over limit of %d pages (%s)",
- max, PagesToUnitOfBytes(max), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages))
- } else if min > memoryLimitPages {
- return fmt.Errorf("min %d pages (%s) over limit of %d pages (%s)",
- min, PagesToUnitOfBytes(min), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages))
- } else if min > max {
- return fmt.Errorf("min %d pages (%s) > max %d pages (%s)",
- min, PagesToUnitOfBytes(min), max, PagesToUnitOfBytes(max))
- } else if capacity < min {
- return fmt.Errorf("capacity %d pages (%s) less than minimum %d pages (%s)",
- capacity, PagesToUnitOfBytes(capacity), min, PagesToUnitOfBytes(min))
- } else if capacity > memoryLimitPages {
- return fmt.Errorf("capacity %d pages (%s) over limit of %d pages (%s)",
- capacity, PagesToUnitOfBytes(capacity), memoryLimitPages, PagesToUnitOfBytes(memoryLimitPages))
- }
- return nil
-}
-
-type GlobalType struct {
- ValType ValueType
- Mutable bool
-}
-
-type Global struct {
- Type GlobalType
- Init ConstantExpression
-}
-
-type ConstantExpression struct {
- Opcode Opcode
- Data []byte
-}
-
-// Export is the binary representation of an export indicated by Type
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-export
-type Export struct {
- Type ExternType
-
- // Name is what the host refers to this definition as.
- Name string
-
- // Index is the index of the definition to export, the index is by Type
- // e.g. If ExternTypeFunc, this is a position in the function index.
- Index Index
-}
-
-// Code is an entry in the Module.CodeSection containing the locals and body of the function.
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-code
-type Code struct {
- // LocalTypes are any function-scoped variables in insertion order.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-local
- LocalTypes []ValueType
-
- // Body is a sequence of expressions ending in OpcodeEnd
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-expr
- Body []byte
-
- // GoFunc is non-nil when IsHostFunction and defined in go, either
- // api.GoFunction or api.GoModuleFunction. When present, LocalTypes and Body must
- // be nil.
- //
- // Note: This has no serialization format, so is not encodable.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#host-functions%E2%91%A2
- GoFunc interface{}
-
- // BodyOffsetInCodeSection is the offset of the beginning of the body in the code section.
- // This is used for DWARF based stack trace where a program counter represents an offset in code section.
- BodyOffsetInCodeSection uint64
-}
-
-type DataSegment struct {
- OffsetExpression ConstantExpression
- Init []byte
- Passive bool
-}
-
-// IsPassive returns true if this data segment is "passive" in the sense that memory offset and
-// index is determined at runtime and used by OpcodeMemoryInitName instruction in the bulk memory
-// operations proposal.
-//
-// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions
-func (d *DataSegment) IsPassive() bool {
- return d.Passive
-}
-
-// NameSection represent the known custom name subsections defined in the WebAssembly Binary Format
-//
-// Note: This can be nil if no names were decoded for any reason including configuration.
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0
-type NameSection struct {
- // ModuleName is the symbolic identifier for a module. e.g. math
- //
- // Note: This can be empty for any reason including configuration.
- ModuleName string
-
- // FunctionNames is an association of a function index to its symbolic identifier. e.g. add
- //
- // * the key (idx) is in the function index, where module defined functions are preceded by imported ones.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#functions%E2%91%A7
- //
- // For example, assuming the below text format is the second import, you would expect FunctionNames[1] = "mul"
- // (import "Math" "Mul" (func $mul (param $x f32) (param $y f32) (result f32)))
- //
- // Note: FunctionNames are only used for debugging. At runtime, functions are called based on raw numeric index.
- // Note: This can be nil for any reason including configuration.
- FunctionNames NameMap
-
- // LocalNames contains symbolic names for function parameters or locals that have one.
- //
- // Note: In the Text Format, function local names can inherit parameter
- // names from their type. Here are some examples:
- // * (module (import (func (param $x i32) (param i32))) (func (type 0))) = [{0, {x,0}}]
- // * (module (import (func (param i32) (param $y i32))) (func (type 0) (local $z i32))) = [0, [{y,1},{z,2}]]
- // * (module (func (param $x i32) (local $y i32) (local $z i32))) = [{x,0},{y,1},{z,2}]
- //
- // Note: LocalNames are only used for debugging. At runtime, locals are called based on raw numeric index.
- // Note: This can be nil for any reason including configuration.
- LocalNames IndirectNameMap
-
- // ResultNames is a wazero-specific mechanism to store result names.
- ResultNames IndirectNameMap
-}
-
-// CustomSection contains the name and raw data of a custom section.
-type CustomSection struct {
- Name string
- Data []byte
-}
-
-// NameMap associates an index with any associated names.
-//
-// Note: Often the index bridges multiple sections. For example, the function index starts with any
-// ExternTypeFunc in the Module.ImportSection followed by the Module.FunctionSection
-//
-// Note: NameMap is unique by NameAssoc.Index, but NameAssoc.Name needn't be unique.
-// Note: When encoding in the Binary format, this must be ordered by NameAssoc.Index
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-namemap
-type NameMap []NameAssoc
-
-type NameAssoc struct {
- Index Index
- Name string
-}
-
-// IndirectNameMap associates an index with an association of names.
-//
-// Note: IndirectNameMap is unique by NameMapAssoc.Index, but NameMapAssoc.NameMap needn't be unique.
-// Note: When encoding in the Binary format, this must be ordered by NameMapAssoc.Index
-// https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-indirectnamemap
-type IndirectNameMap []NameMapAssoc
-
-type NameMapAssoc struct {
- Index Index
- NameMap NameMap
-}
-
-// AllDeclarations returns all declarations for functions, globals, memories and tables in a module including imported ones.
-func (m *Module) AllDeclarations() (functions []Index, globals []GlobalType, memory *Memory, tables []Table, err error) {
- for i := range m.ImportSection {
- imp := &m.ImportSection[i]
- switch imp.Type {
- case ExternTypeFunc:
- functions = append(functions, imp.DescFunc)
- case ExternTypeGlobal:
- globals = append(globals, imp.DescGlobal)
- case ExternTypeMemory:
- memory = imp.DescMem
- case ExternTypeTable:
- tables = append(tables, imp.DescTable)
- }
- }
-
- functions = append(functions, m.FunctionSection...)
- for i := range m.GlobalSection {
- g := &m.GlobalSection[i]
- globals = append(globals, g.Type)
- }
- if m.MemorySection != nil {
- if memory != nil { // shouldn't be possible due to Validate
- err = errors.New("at most one table allowed in module")
- return
- }
- memory = m.MemorySection
- }
- if m.TableSection != nil {
- tables = append(tables, m.TableSection...)
- }
- return
-}
-
-// SectionID identifies the sections of a Module in the WebAssembly 1.0 (20191205) Binary Format.
-//
-// Note: these are defined in the wasm package, instead of the binary package, as a key per section is needed regardless
-// of format, and deferring to the binary type avoids confusion.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#sections%E2%91%A0
-type SectionID = byte
-
-const (
- // SectionIDCustom includes the standard defined NameSection and possibly others not defined in the standard.
- SectionIDCustom SectionID = iota // don't add anything not in https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#sections%E2%91%A0
- SectionIDType
- SectionIDImport
- SectionIDFunction
- SectionIDTable
- SectionIDMemory
- SectionIDGlobal
- SectionIDExport
- SectionIDStart
- SectionIDElement
- SectionIDCode
- SectionIDData
-
- // SectionIDDataCount may exist in WebAssembly 2.0 or WebAssembly 1.0 with CoreFeatureBulkMemoryOperations enabled.
- //
- // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/binary/modules.html#data-count-section
- // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/appendix/changes.html#bulk-memory-and-table-instructions
- SectionIDDataCount
-)
-
-// SectionIDName returns the canonical name of a module section.
-// https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#sections%E2%91%A0
-func SectionIDName(sectionID SectionID) string {
- switch sectionID {
- case SectionIDCustom:
- return "custom"
- case SectionIDType:
- return "type"
- case SectionIDImport:
- return "import"
- case SectionIDFunction:
- return "function"
- case SectionIDTable:
- return "table"
- case SectionIDMemory:
- return "memory"
- case SectionIDGlobal:
- return "global"
- case SectionIDExport:
- return "export"
- case SectionIDStart:
- return "start"
- case SectionIDElement:
- return "element"
- case SectionIDCode:
- return "code"
- case SectionIDData:
- return "data"
- case SectionIDDataCount:
- return "data_count"
- }
- return "unknown"
-}
-
-// ValueType is an alias of api.ValueType defined to simplify imports.
-type ValueType = api.ValueType
-
-const (
- ValueTypeI32 = api.ValueTypeI32
- ValueTypeI64 = api.ValueTypeI64
- ValueTypeF32 = api.ValueTypeF32
- ValueTypeF64 = api.ValueTypeF64
- // TODO: ValueTypeV128 is not exposed in the api pkg yet.
- ValueTypeV128 ValueType = 0x7b
- // TODO: ValueTypeFuncref is not exposed in the api pkg yet.
- ValueTypeFuncref ValueType = 0x70
- ValueTypeExternref = api.ValueTypeExternref
-)
-
-// ValueTypeName is an alias of api.ValueTypeName defined to simplify imports.
-func ValueTypeName(t ValueType) string {
- if t == ValueTypeFuncref {
- return "funcref"
- } else if t == ValueTypeV128 {
- return "v128"
- }
- return api.ValueTypeName(t)
-}
-
-func isReferenceValueType(vt ValueType) bool {
- return vt == ValueTypeExternref || vt == ValueTypeFuncref
-}
-
-// ExternType is an alias of api.ExternType defined to simplify imports.
-type ExternType = api.ExternType
-
-const (
- ExternTypeFunc = api.ExternTypeFunc
- ExternTypeFuncName = api.ExternTypeFuncName
- ExternTypeTable = api.ExternTypeTable
- ExternTypeTableName = api.ExternTypeTableName
- ExternTypeMemory = api.ExternTypeMemory
- ExternTypeMemoryName = api.ExternTypeMemoryName
- ExternTypeGlobal = api.ExternTypeGlobal
- ExternTypeGlobalName = api.ExternTypeGlobalName
-)
-
-// ExternTypeName is an alias of api.ExternTypeName defined to simplify imports.
-func ExternTypeName(t ValueType) string {
- return api.ExternTypeName(t)
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go
deleted file mode 100644
index 20c733e6f..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance.go
+++ /dev/null
@@ -1,251 +0,0 @@
-package wasm
-
-import (
- "context"
- "errors"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/sys"
-)
-
-// FailIfClosed returns a sys.ExitError if CloseWithExitCode was called.
-func (m *ModuleInstance) FailIfClosed() (err error) {
- if closed := m.Closed.Load(); closed != 0 {
- switch closed & exitCodeFlagMask {
- case exitCodeFlagResourceClosed:
- case exitCodeFlagResourceNotClosed:
- // This happens when this module is closed asynchronously in CloseModuleOnCanceledOrTimeout,
- // and the closure of resources have been deferred here.
- _ = m.ensureResourcesClosed(context.Background())
- }
- return sys.NewExitError(uint32(closed >> 32)) // Unpack the high order bits as the exit code.
- }
- return nil
-}
-
-// CloseModuleOnCanceledOrTimeout take a context `ctx`, which might be a Cancel or Timeout context,
-// and spawns the Goroutine to check the context is canceled ot deadline exceeded. If it reaches
-// one of the conditions, it sets the appropriate exit code.
-//
-// Callers of this function must invoke the returned context.CancelFunc to release the spawned Goroutine.
-func (m *ModuleInstance) CloseModuleOnCanceledOrTimeout(ctx context.Context) context.CancelFunc {
- // Creating an empty channel in this case is a bit more efficient than
- // creating a context.Context and canceling it with the same effect. We
- // really just need to be notified when to stop listening to the users
- // context. Closing the channel will unblock the select in the goroutine
- // causing it to return an stop listening to ctx.Done().
- cancelChan := make(chan struct{})
- go m.closeModuleOnCanceledOrTimeout(ctx, cancelChan)
- return func() { close(cancelChan) }
-}
-
-// closeModuleOnCanceledOrTimeout is extracted from CloseModuleOnCanceledOrTimeout for testing.
-func (m *ModuleInstance) closeModuleOnCanceledOrTimeout(ctx context.Context, cancelChan <-chan struct{}) {
- select {
- case <-ctx.Done():
- select {
- case <-cancelChan:
- // In some cases by the time this goroutine is scheduled, the caller
- // has already closed both the context and the cancelChan. In this
- // case go will randomize which branch of the outer select to enter
- // and we don't want to close the module.
- default:
- // This is the same logic as CloseWithCtxErr except this calls closeWithExitCodeWithoutClosingResource
- // so that we can defer the resource closure in FailIfClosed.
- switch {
- case errors.Is(ctx.Err(), context.Canceled):
- // TODO: figure out how to report error here.
- _ = m.closeWithExitCodeWithoutClosingResource(sys.ExitCodeContextCanceled)
- case errors.Is(ctx.Err(), context.DeadlineExceeded):
- // TODO: figure out how to report error here.
- _ = m.closeWithExitCodeWithoutClosingResource(sys.ExitCodeDeadlineExceeded)
- }
- }
- case <-cancelChan:
- }
-}
-
-// CloseWithCtxErr closes the module with an exit code based on the type of
-// error reported by the context.
-//
-// If the context's error is unknown or nil, the module does not close.
-func (m *ModuleInstance) CloseWithCtxErr(ctx context.Context) {
- switch {
- case errors.Is(ctx.Err(), context.Canceled):
- // TODO: figure out how to report error here.
- _ = m.CloseWithExitCode(ctx, sys.ExitCodeContextCanceled)
- case errors.Is(ctx.Err(), context.DeadlineExceeded):
- // TODO: figure out how to report error here.
- _ = m.CloseWithExitCode(ctx, sys.ExitCodeDeadlineExceeded)
- }
-}
-
-// Name implements the same method as documented on api.Module
-func (m *ModuleInstance) Name() string {
- return m.ModuleName
-}
-
-// String implements the same method as documented on api.Module
-func (m *ModuleInstance) String() string {
- return fmt.Sprintf("Module[%s]", m.Name())
-}
-
-// Close implements the same method as documented on api.Module.
-func (m *ModuleInstance) Close(ctx context.Context) (err error) {
- return m.CloseWithExitCode(ctx, 0)
-}
-
-// CloseWithExitCode implements the same method as documented on api.Module.
-func (m *ModuleInstance) CloseWithExitCode(ctx context.Context, exitCode uint32) (err error) {
- if !m.setExitCode(exitCode, exitCodeFlagResourceClosed) {
- return nil // not an error to have already closed
- }
- _ = m.s.deleteModule(m)
- return m.ensureResourcesClosed(ctx)
-}
-
-// IsClosed implements the same method as documented on api.Module.
-func (m *ModuleInstance) IsClosed() bool {
- return m.Closed.Load() != 0
-}
-
-func (m *ModuleInstance) closeWithExitCodeWithoutClosingResource(exitCode uint32) (err error) {
- if !m.setExitCode(exitCode, exitCodeFlagResourceNotClosed) {
- return nil // not an error to have already closed
- }
- _ = m.s.deleteModule(m)
- return nil
-}
-
-// closeWithExitCode is the same as CloseWithExitCode besides this doesn't delete it from Store.moduleList.
-func (m *ModuleInstance) closeWithExitCode(ctx context.Context, exitCode uint32) (err error) {
- if !m.setExitCode(exitCode, exitCodeFlagResourceClosed) {
- return nil // not an error to have already closed
- }
- return m.ensureResourcesClosed(ctx)
-}
-
-type exitCodeFlag = uint64
-
-const exitCodeFlagMask = 0xff
-
-const (
- // exitCodeFlagResourceClosed indicates that the module was closed and resources were already closed.
- exitCodeFlagResourceClosed = 1 << iota
- // exitCodeFlagResourceNotClosed indicates that the module was closed while resources are not closed yet.
- exitCodeFlagResourceNotClosed
-)
-
-func (m *ModuleInstance) setExitCode(exitCode uint32, flag exitCodeFlag) bool {
- closed := flag | uint64(exitCode)<<32 // Store exitCode as high-order bits.
- return m.Closed.CompareAndSwap(0, closed)
-}
-
-// ensureResourcesClosed ensures that resources assigned to ModuleInstance is released.
-// Only one call will happen per module, due to external atomic guards on Closed.
-func (m *ModuleInstance) ensureResourcesClosed(ctx context.Context) (err error) {
- if closeNotifier := m.CloseNotifier; closeNotifier != nil { // experimental
- closeNotifier.CloseNotify(ctx, uint32(m.Closed.Load()>>32))
- m.CloseNotifier = nil
- }
-
- if sysCtx := m.Sys; sysCtx != nil { // nil if from HostModuleBuilder
- err = sysCtx.FS().Close()
- m.Sys = nil
- }
-
- if mem := m.MemoryInstance; mem != nil {
- if mem.expBuffer != nil {
- mem.expBuffer.Free()
- mem.expBuffer = nil
- }
- }
-
- if m.CodeCloser != nil {
- if e := m.CodeCloser.Close(ctx); err == nil {
- err = e
- }
- m.CodeCloser = nil
- }
- return err
-}
-
-// Memory implements the same method as documented on api.Module.
-func (m *ModuleInstance) Memory() api.Memory {
- return m.MemoryInstance
-}
-
-// ExportedMemory implements the same method as documented on api.Module.
-func (m *ModuleInstance) ExportedMemory(name string) api.Memory {
- _, err := m.getExport(name, ExternTypeMemory)
- if err != nil {
- return nil
- }
- // We Assume that we have at most one memory.
- return m.MemoryInstance
-}
-
-// ExportedMemoryDefinitions implements the same method as documented on
-// api.Module.
-func (m *ModuleInstance) ExportedMemoryDefinitions() map[string]api.MemoryDefinition {
- // Special case as we currently only support one memory.
- if mem := m.MemoryInstance; mem != nil {
- // Now, find out if it is exported
- for name, exp := range m.Exports {
- if exp.Type == ExternTypeMemory {
- return map[string]api.MemoryDefinition{name: mem.definition}
- }
- }
- }
- return map[string]api.MemoryDefinition{}
-}
-
-// ExportedFunction implements the same method as documented on api.Module.
-func (m *ModuleInstance) ExportedFunction(name string) api.Function {
- exp, err := m.getExport(name, ExternTypeFunc)
- if err != nil {
- return nil
- }
- return m.Engine.NewFunction(exp.Index)
-}
-
-// ExportedFunctionDefinitions implements the same method as documented on
-// api.Module.
-func (m *ModuleInstance) ExportedFunctionDefinitions() map[string]api.FunctionDefinition {
- result := map[string]api.FunctionDefinition{}
- for name, exp := range m.Exports {
- if exp.Type == ExternTypeFunc {
- result[name] = m.Source.FunctionDefinition(exp.Index)
- }
- }
- return result
-}
-
-// GlobalVal is an internal hack to get the lower 64 bits of a global.
-func (m *ModuleInstance) GlobalVal(idx Index) uint64 {
- return m.Globals[idx].Val
-}
-
-// ExportedGlobal implements the same method as documented on api.Module.
-func (m *ModuleInstance) ExportedGlobal(name string) api.Global {
- exp, err := m.getExport(name, ExternTypeGlobal)
- if err != nil {
- return nil
- }
- g := m.Globals[exp.Index]
- if g.Type.Mutable {
- return mutableGlobal{g: g}
- }
- return constantGlobal{g: g}
-}
-
-// NumGlobal implements experimental.InternalModule.
-func (m *ModuleInstance) NumGlobal() int {
- return len(m.Globals)
-}
-
-// Global implements experimental.InternalModule.
-func (m *ModuleInstance) Global(idx int) api.Global {
- return constantGlobal{g: m.Globals[idx]}
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go
deleted file mode 100644
index 442d26a22..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/module_instance_lookup.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package wasm
-
-import (
- "context"
- "fmt"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/internalapi"
-)
-
-// LookupFunction looks up the table by the given index, and returns the api.Function implementation if found,
-// otherwise this panics according to the same semantics as call_indirect instruction.
-// Currently, this is only used by emscripten which needs to do call_indirect-like operation in the host function.
-func (m *ModuleInstance) LookupFunction(t *TableInstance, typeId FunctionTypeID, tableOffset Index) api.Function {
- fm, index := m.Engine.LookupFunction(t, typeId, tableOffset)
- if source := fm.Source; source.IsHostModule {
- // This case, the found function is a host function stored in the table. Generally, Engine.NewFunction are only
- // responsible for calling Wasm-defined functions (not designed for calling Go functions!). Hence we need to wrap
- // the host function as a special case.
- def := &source.FunctionDefinitionSection[index]
- goF := source.CodeSection[index].GoFunc
- switch typed := goF.(type) {
- case api.GoFunction:
- // GoFunction doesn't need looked up module.
- return &lookedUpGoFunction{def: def, g: goFunctionAsGoModuleFunction(typed)}
- case api.GoModuleFunction:
- return &lookedUpGoFunction{def: def, lookedUpModule: m, g: typed}
- default:
- panic(fmt.Sprintf("unexpected GoFunc type: %T", goF))
- }
- } else {
- return fm.Engine.NewFunction(index)
- }
-}
-
-// lookedUpGoFunction implements lookedUpGoModuleFunction.
-type lookedUpGoFunction struct {
- internalapi.WazeroOnly
- def *FunctionDefinition
- // lookedUpModule is the *ModuleInstance from which this Go function is looked up, i.e. owner of the table.
- lookedUpModule *ModuleInstance
- g api.GoModuleFunction
-}
-
-// goFunctionAsGoModuleFunction converts api.GoFunction to api.GoModuleFunction which ignores the api.Module argument.
-func goFunctionAsGoModuleFunction(g api.GoFunction) api.GoModuleFunction {
- return api.GoModuleFunc(func(ctx context.Context, _ api.Module, stack []uint64) {
- g.Call(ctx, stack)
- })
-}
-
-// Definition implements api.Function.
-func (l *lookedUpGoFunction) Definition() api.FunctionDefinition { return l.def }
-
-// Call implements api.Function.
-func (l *lookedUpGoFunction) Call(ctx context.Context, params ...uint64) ([]uint64, error) {
- typ := l.def.Functype
- stackSize := typ.ParamNumInUint64
- rn := typ.ResultNumInUint64
- if rn > stackSize {
- stackSize = rn
- }
- stack := make([]uint64, stackSize)
- copy(stack, params)
- return stack[:rn], l.CallWithStack(ctx, stack)
-}
-
-// CallWithStack implements api.Function.
-func (l *lookedUpGoFunction) CallWithStack(ctx context.Context, stack []uint64) error {
- // The Go host function always needs to access caller's module, in this case the one holding the table.
- l.g.Call(ctx, l.lookedUpModule, stack)
- return nil
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/store.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/store.go
deleted file mode 100644
index c7909c67c..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/store.go
+++ /dev/null
@@ -1,679 +0,0 @@
-package wasm
-
-import (
- "context"
- "encoding/binary"
- "errors"
- "fmt"
- "sync"
- "sync/atomic"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/experimental"
- "github.com/tetratelabs/wazero/internal/expctxkeys"
- "github.com/tetratelabs/wazero/internal/internalapi"
- "github.com/tetratelabs/wazero/internal/leb128"
- internalsys "github.com/tetratelabs/wazero/internal/sys"
- "github.com/tetratelabs/wazero/sys"
-)
-
-// nameToModuleShrinkThreshold is the size the nameToModule map can grow to
-// before it starts to be monitored for shrinking.
-// The capacity will never be smaller than this once the threshold is met.
-const nameToModuleShrinkThreshold = 100
-
-type (
- // Store is the runtime representation of "instantiated" Wasm module and objects.
- // Multiple modules can be instantiated within a single store, and each instance,
- // (e.g. function instance) can be referenced by other module instances in a Store via Module.ImportSection.
- //
- // Every type whose name ends with "Instance" suffix belongs to exactly one store.
- //
- // Note that store is not thread (concurrency) safe, meaning that using single Store
- // via multiple goroutines might result in race conditions. In that case, the invocation
- // and access to any methods and field of Store must be guarded by mutex.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#store%E2%91%A0
- Store struct {
- // moduleList ensures modules are closed in reverse initialization order.
- moduleList *ModuleInstance // guarded by mux
-
- // nameToModule holds the instantiated Wasm modules by module name from Instantiate.
- // It ensures no race conditions instantiating two modules of the same name.
- nameToModule map[string]*ModuleInstance // guarded by mux
-
- // nameToModuleCap tracks the growth of the nameToModule map in order to
- // track when to shrink it.
- nameToModuleCap int // guarded by mux
-
- // EnabledFeatures are read-only to allow optimizations.
- EnabledFeatures api.CoreFeatures
-
- // Engine is a global context for a Store which is in responsible for compilation and execution of Wasm modules.
- Engine Engine
-
- // typeIDs maps each FunctionType.String() to a unique FunctionTypeID. This is used at runtime to
- // do type-checks on indirect function calls.
- typeIDs map[string]FunctionTypeID
-
- // functionMaxTypes represents the limit on the number of function types in a store.
- // Note: this is fixed to 2^27 but have this a field for testability.
- functionMaxTypes uint32
-
- // mux is used to guard the fields from concurrent access.
- mux sync.RWMutex
- }
-
- // ModuleInstance represents instantiated wasm module.
- // The difference from the spec is that in wazero, a ModuleInstance holds pointers
- // to the instances, rather than "addresses" (i.e. index to Store.Functions, Globals, etc) for convenience.
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-moduleinst
- //
- // This implements api.Module.
- ModuleInstance struct {
- internalapi.WazeroOnlyType
-
- ModuleName string
- Exports map[string]*Export
- Globals []*GlobalInstance
- MemoryInstance *MemoryInstance
- Tables []*TableInstance
-
- // Engine implements function calls for this module.
- Engine ModuleEngine
-
- // TypeIDs is index-correlated with types and holds typeIDs which is uniquely assigned to a type by store.
- // This is necessary to achieve fast runtime type checking for indirect function calls at runtime.
- TypeIDs []FunctionTypeID
-
- // DataInstances holds data segments bytes of the module.
- // This is only used by bulk memory operations.
- //
- // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/runtime.html#data-instances
- DataInstances []DataInstance
-
- // ElementInstances holds the element instance, and each holds the references to either functions
- // or external objects (unimplemented).
- ElementInstances []ElementInstance
-
- // Sys is exposed for use in special imports such as WASI, assemblyscript.
- //
- // # Notes
- //
- // - This is a part of ModuleInstance so that scope and Close is coherent.
- // - This is not exposed outside this repository (as a host function
- // parameter) because we haven't thought through capabilities based
- // security implications.
- Sys *internalsys.Context
-
- // Closed is used both to guard moduleEngine.CloseWithExitCode and to store the exit code.
- //
- // The update value is closedType + exitCode << 32. This ensures an exit code of zero isn't mistaken for never closed.
- //
- // Note: Exclusively reading and updating this with atomics guarantees cross-goroutine observations.
- // See /RATIONALE.md
- Closed atomic.Uint64
-
- // CodeCloser is non-nil when the code should be closed after this module.
- CodeCloser api.Closer
-
- // s is the Store on which this module is instantiated.
- s *Store
- // prev and next hold the nodes in the linked list of ModuleInstance held by Store.
- prev, next *ModuleInstance
- // Source is a pointer to the Module from which this ModuleInstance derives.
- Source *Module
-
- // CloseNotifier is an experimental hook called once on close.
- CloseNotifier experimental.CloseNotifier
- }
-
- // DataInstance holds bytes corresponding to the data segment in a module.
- //
- // https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/runtime.html#data-instances
- DataInstance = []byte
-
- // GlobalInstance represents a global instance in a store.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#global-instances%E2%91%A0
- GlobalInstance struct {
- Type GlobalType
- // Val holds a 64-bit representation of the actual value.
- // If me is non-nil, the value will not be updated and the current value is stored in the module engine.
- Val uint64
- // ValHi is only used for vector type globals, and holds the higher bits of the vector.
- // If me is non-nil, the value will not be updated and the current value is stored in the module engine.
- ValHi uint64
- // Me is the module engine that owns this global instance.
- // The .Val and .ValHi fields are only valid when me is nil.
- // If me is non-nil, the value is stored in the module engine.
- Me ModuleEngine
- Index Index
- }
-
- // FunctionTypeID is a uniquely assigned integer for a function type.
- // This is wazero specific runtime object and specific to a store,
- // and used at runtime to do type-checks on indirect function calls.
- FunctionTypeID uint32
-)
-
-// The wazero specific limitations described at RATIONALE.md.
-const maximumFunctionTypes = 1 << 27
-
-// GetFunctionTypeID is used by emscripten.
-func (m *ModuleInstance) GetFunctionTypeID(t *FunctionType) FunctionTypeID {
- id, err := m.s.GetFunctionTypeID(t)
- if err != nil {
- // This is not recoverable in practice since the only error GetFunctionTypeID returns is
- // when there's too many function types in the store.
- panic(err)
- }
- return id
-}
-
-func (m *ModuleInstance) buildElementInstances(elements []ElementSegment) {
- m.ElementInstances = make([][]Reference, len(elements))
- for i, elm := range elements {
- if elm.Type == RefTypeFuncref && elm.Mode == ElementModePassive {
- // Only passive elements can be access as element instances.
- // See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/modules.html#element-segments
- inits := elm.Init
- inst := make([]Reference, len(inits))
- m.ElementInstances[i] = inst
- for j, idx := range inits {
- if index, ok := unwrapElementInitGlobalReference(idx); ok {
- global := m.Globals[index]
- inst[j] = Reference(global.Val)
- } else {
- if idx != ElementInitNullReference {
- inst[j] = m.Engine.FunctionInstanceReference(idx)
- }
- }
- }
- }
- }
-}
-
-func (m *ModuleInstance) applyElements(elems []ElementSegment) {
- for elemI := range elems {
- elem := &elems[elemI]
- if !elem.IsActive() ||
- // Per https://github.com/WebAssembly/spec/issues/1427 init can be no-op.
- len(elem.Init) == 0 {
- continue
- }
- var offset uint32
- if elem.OffsetExpr.Opcode == OpcodeGlobalGet {
- // Ignore error as it's already validated.
- globalIdx, _, _ := leb128.LoadUint32(elem.OffsetExpr.Data)
- global := m.Globals[globalIdx]
- offset = uint32(global.Val)
- } else {
- // Ignore error as it's already validated.
- o, _, _ := leb128.LoadInt32(elem.OffsetExpr.Data)
- offset = uint32(o)
- }
-
- table := m.Tables[elem.TableIndex]
- references := table.References
- if int(offset)+len(elem.Init) > len(references) {
- // ErrElementOffsetOutOfBounds is the error raised when the active element offset exceeds the table length.
- // Before CoreFeatureReferenceTypes, this was checked statically before instantiation, after the proposal,
- // this must be raised as runtime error (as in assert_trap in spectest), not even an instantiation error.
- // https://github.com/WebAssembly/spec/blob/d39195773112a22b245ffbe864bab6d1182ccb06/test/core/linking.wast#L264-L274
- //
- // In wazero, we ignore it since in any way, the instantiated module and engines are fine and can be used
- // for function invocations.
- return
- }
-
- if table.Type == RefTypeExternref {
- for i := 0; i < len(elem.Init); i++ {
- references[offset+uint32(i)] = Reference(0)
- }
- } else {
- for i, init := range elem.Init {
- if init == ElementInitNullReference {
- continue
- }
-
- var ref Reference
- if index, ok := unwrapElementInitGlobalReference(init); ok {
- global := m.Globals[index]
- ref = Reference(global.Val)
- } else {
- ref = m.Engine.FunctionInstanceReference(index)
- }
- references[offset+uint32(i)] = ref
- }
- }
- }
-}
-
-// validateData ensures that data segments are valid in terms of memory boundary.
-// Note: this is used only when bulk-memory/reference type feature is disabled.
-func (m *ModuleInstance) validateData(data []DataSegment) (err error) {
- for i := range data {
- d := &data[i]
- if !d.IsPassive() {
- offset := int(executeConstExpressionI32(m.Globals, &d.OffsetExpression))
- ceil := offset + len(d.Init)
- if offset < 0 || ceil > len(m.MemoryInstance.Buffer) {
- return fmt.Errorf("%s[%d]: out of bounds memory access", SectionIDName(SectionIDData), i)
- }
- }
- }
- return
-}
-
-// applyData uses the given data segments and mutate the memory according to the initial contents on it
-// and populate the `DataInstances`. This is called after all the validation phase passes and out of
-// bounds memory access error here is not a validation error, but rather a runtime error.
-func (m *ModuleInstance) applyData(data []DataSegment) error {
- m.DataInstances = make([][]byte, len(data))
- for i := range data {
- d := &data[i]
- m.DataInstances[i] = d.Init
- if !d.IsPassive() {
- offset := executeConstExpressionI32(m.Globals, &d.OffsetExpression)
- if offset < 0 || int(offset)+len(d.Init) > len(m.MemoryInstance.Buffer) {
- return fmt.Errorf("%s[%d]: out of bounds memory access", SectionIDName(SectionIDData), i)
- }
- copy(m.MemoryInstance.Buffer[offset:], d.Init)
- }
- }
- return nil
-}
-
-// GetExport returns an export of the given name and type or errs if not exported or the wrong type.
-func (m *ModuleInstance) getExport(name string, et ExternType) (*Export, error) {
- exp, ok := m.Exports[name]
- if !ok {
- return nil, fmt.Errorf("%q is not exported in module %q", name, m.ModuleName)
- }
- if exp.Type != et {
- return nil, fmt.Errorf("export %q in module %q is a %s, not a %s", name, m.ModuleName, ExternTypeName(exp.Type), ExternTypeName(et))
- }
- return exp, nil
-}
-
-func NewStore(enabledFeatures api.CoreFeatures, engine Engine) *Store {
- return &Store{
- nameToModule: map[string]*ModuleInstance{},
- nameToModuleCap: nameToModuleShrinkThreshold,
- EnabledFeatures: enabledFeatures,
- Engine: engine,
- typeIDs: map[string]FunctionTypeID{},
- functionMaxTypes: maximumFunctionTypes,
- }
-}
-
-// Instantiate uses name instead of the Module.NameSection ModuleName as it allows instantiating the same module under
-// different names safely and concurrently.
-//
-// * ctx: the default context used for function calls.
-// * name: the name of the module.
-// * sys: the system context, which will be closed (SysContext.Close) on ModuleInstance.Close.
-//
-// Note: Module.Validate must be called prior to instantiation.
-func (s *Store) Instantiate(
- ctx context.Context,
- module *Module,
- name string,
- sys *internalsys.Context,
- typeIDs []FunctionTypeID,
-) (*ModuleInstance, error) {
- // Instantiate the module and add it to the store so that other modules can import it.
- m, err := s.instantiate(ctx, module, name, sys, typeIDs)
- if err != nil {
- return nil, err
- }
-
- // Now that the instantiation is complete without error, add it.
- if err = s.registerModule(m); err != nil {
- _ = m.Close(ctx)
- return nil, err
- }
- return m, nil
-}
-
-func (s *Store) instantiate(
- ctx context.Context,
- module *Module,
- name string,
- sysCtx *internalsys.Context,
- typeIDs []FunctionTypeID,
-) (m *ModuleInstance, err error) {
- m = &ModuleInstance{ModuleName: name, TypeIDs: typeIDs, Sys: sysCtx, s: s, Source: module}
-
- m.Tables = make([]*TableInstance, int(module.ImportTableCount)+len(module.TableSection))
- m.Globals = make([]*GlobalInstance, int(module.ImportGlobalCount)+len(module.GlobalSection))
- m.Engine, err = s.Engine.NewModuleEngine(module, m)
- if err != nil {
- return nil, err
- }
-
- if err = m.resolveImports(ctx, module); err != nil {
- return nil, err
- }
-
- err = m.buildTables(module,
- // As of reference-types proposal, boundary check must be done after instantiation.
- s.EnabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes))
- if err != nil {
- return nil, err
- }
-
- allocator, _ := ctx.Value(expctxkeys.MemoryAllocatorKey{}).(experimental.MemoryAllocator)
-
- m.buildGlobals(module, m.Engine.FunctionInstanceReference)
- m.buildMemory(module, allocator)
- m.Exports = module.Exports
- for _, exp := range m.Exports {
- if exp.Type == ExternTypeTable {
- t := m.Tables[exp.Index]
- t.involvingModuleInstances = append(t.involvingModuleInstances, m)
- }
- }
-
- // As of reference types proposal, data segment validation must happen after instantiation,
- // and the side effect must persist even if there's out of bounds error after instantiation.
- // https://github.com/WebAssembly/spec/blob/d39195773112a22b245ffbe864bab6d1182ccb06/test/core/linking.wast#L395-L405
- if !s.EnabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) {
- if err = m.validateData(module.DataSection); err != nil {
- return nil, err
- }
- }
-
- // After engine creation, we can create the funcref element instances and initialize funcref type globals.
- m.buildElementInstances(module.ElementSection)
-
- // Now all the validation passes, we are safe to mutate memory instances (possibly imported ones).
- if err = m.applyData(module.DataSection); err != nil {
- return nil, err
- }
-
- m.applyElements(module.ElementSection)
-
- m.Engine.DoneInstantiation()
-
- // Execute the start function.
- if module.StartSection != nil {
- funcIdx := *module.StartSection
- ce := m.Engine.NewFunction(funcIdx)
- _, err = ce.Call(ctx)
- if exitErr, ok := err.(*sys.ExitError); ok { // Don't wrap an exit error!
- return nil, exitErr
- } else if err != nil {
- return nil, fmt.Errorf("start %s failed: %w", module.funcDesc(SectionIDFunction, funcIdx), err)
- }
- }
- return
-}
-
-func (m *ModuleInstance) resolveImports(ctx context.Context, module *Module) (err error) {
- // Check if ctx contains an ImportResolver.
- resolveImport, _ := ctx.Value(expctxkeys.ImportResolverKey{}).(experimental.ImportResolver)
-
- for moduleName, imports := range module.ImportPerModule {
- var importedModule *ModuleInstance
- if resolveImport != nil {
- if v := resolveImport(moduleName); v != nil {
- importedModule = v.(*ModuleInstance)
- }
- }
- if importedModule == nil {
- importedModule, err = m.s.module(moduleName)
- if err != nil {
- return err
- }
- }
-
- for _, i := range imports {
- var imported *Export
- imported, err = importedModule.getExport(i.Name, i.Type)
- if err != nil {
- return
- }
-
- switch i.Type {
- case ExternTypeFunc:
- expectedType := &module.TypeSection[i.DescFunc]
- src := importedModule.Source
- actual := src.typeOfFunction(imported.Index)
- if !actual.EqualsSignature(expectedType.Params, expectedType.Results) {
- err = errorInvalidImport(i, fmt.Errorf("signature mismatch: %s != %s", expectedType, actual))
- return
- }
-
- m.Engine.ResolveImportedFunction(i.IndexPerType, i.DescFunc, imported.Index, importedModule.Engine)
- case ExternTypeTable:
- expected := i.DescTable
- importedTable := importedModule.Tables[imported.Index]
- if expected.Type != importedTable.Type {
- err = errorInvalidImport(i, fmt.Errorf("table type mismatch: %s != %s",
- RefTypeName(expected.Type), RefTypeName(importedTable.Type)))
- return
- }
-
- if expected.Min > importedTable.Min {
- err = errorMinSizeMismatch(i, expected.Min, importedTable.Min)
- return
- }
-
- if expected.Max != nil {
- expectedMax := *expected.Max
- if importedTable.Max == nil {
- err = errorNoMax(i, expectedMax)
- return
- } else if expectedMax < *importedTable.Max {
- err = errorMaxSizeMismatch(i, expectedMax, *importedTable.Max)
- return
- }
- }
- m.Tables[i.IndexPerType] = importedTable
- importedTable.involvingModuleInstancesMutex.Lock()
- if len(importedTable.involvingModuleInstances) == 0 {
- panic("BUG: involvingModuleInstances must not be nil when it's imported")
- }
- importedTable.involvingModuleInstances = append(importedTable.involvingModuleInstances, m)
- importedTable.involvingModuleInstancesMutex.Unlock()
- case ExternTypeMemory:
- expected := i.DescMem
- importedMemory := importedModule.MemoryInstance
-
- if expected.Min > memoryBytesNumToPages(uint64(len(importedMemory.Buffer))) {
- err = errorMinSizeMismatch(i, expected.Min, importedMemory.Min)
- return
- }
-
- if expected.Max < importedMemory.Max {
- err = errorMaxSizeMismatch(i, expected.Max, importedMemory.Max)
- return
- }
- m.MemoryInstance = importedMemory
- m.Engine.ResolveImportedMemory(importedModule.Engine)
- case ExternTypeGlobal:
- expected := i.DescGlobal
- importedGlobal := importedModule.Globals[imported.Index]
-
- if expected.Mutable != importedGlobal.Type.Mutable {
- err = errorInvalidImport(i, fmt.Errorf("mutability mismatch: %t != %t",
- expected.Mutable, importedGlobal.Type.Mutable))
- return
- }
-
- if expected.ValType != importedGlobal.Type.ValType {
- err = errorInvalidImport(i, fmt.Errorf("value type mismatch: %s != %s",
- ValueTypeName(expected.ValType), ValueTypeName(importedGlobal.Type.ValType)))
- return
- }
- m.Globals[i.IndexPerType] = importedGlobal
- }
- }
- }
- return
-}
-
-func errorMinSizeMismatch(i *Import, expected, actual uint32) error {
- return errorInvalidImport(i, fmt.Errorf("minimum size mismatch: %d > %d", expected, actual))
-}
-
-func errorNoMax(i *Import, expected uint32) error {
- return errorInvalidImport(i, fmt.Errorf("maximum size mismatch: %d, but actual has no max", expected))
-}
-
-func errorMaxSizeMismatch(i *Import, expected, actual uint32) error {
- return errorInvalidImport(i, fmt.Errorf("maximum size mismatch: %d < %d", expected, actual))
-}
-
-func errorInvalidImport(i *Import, err error) error {
- return fmt.Errorf("import %s[%s.%s]: %w", ExternTypeName(i.Type), i.Module, i.Name, err)
-}
-
-// executeConstExpressionI32 executes the ConstantExpression which returns ValueTypeI32.
-// The validity of the expression is ensured when calling this function as this is only called
-// during instantiation phrase, and the validation happens in compilation (validateConstExpression).
-func executeConstExpressionI32(importedGlobals []*GlobalInstance, expr *ConstantExpression) (ret int32) {
- switch expr.Opcode {
- case OpcodeI32Const:
- ret, _, _ = leb128.LoadInt32(expr.Data)
- case OpcodeGlobalGet:
- id, _, _ := leb128.LoadUint32(expr.Data)
- g := importedGlobals[id]
- ret = int32(g.Val)
- }
- return
-}
-
-// initialize initializes the value of this global instance given the const expr and imported globals.
-// funcRefResolver is called to get the actual funcref (engine specific) from the OpcodeRefFunc const expr.
-//
-// Global initialization constant expression can only reference the imported globals.
-// See the note on https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#constant-expressions%E2%91%A0
-func (g *GlobalInstance) initialize(importedGlobals []*GlobalInstance, expr *ConstantExpression, funcRefResolver func(funcIndex Index) Reference) {
- switch expr.Opcode {
- case OpcodeI32Const:
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- v, _, _ := leb128.LoadInt32(expr.Data)
- g.Val = uint64(uint32(v))
- case OpcodeI64Const:
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- v, _, _ := leb128.LoadInt64(expr.Data)
- g.Val = uint64(v)
- case OpcodeF32Const:
- g.Val = uint64(binary.LittleEndian.Uint32(expr.Data))
- case OpcodeF64Const:
- g.Val = binary.LittleEndian.Uint64(expr.Data)
- case OpcodeGlobalGet:
- id, _, _ := leb128.LoadUint32(expr.Data)
- importedG := importedGlobals[id]
- switch importedG.Type.ValType {
- case ValueTypeI32:
- g.Val = uint64(uint32(importedG.Val))
- case ValueTypeI64:
- g.Val = importedG.Val
- case ValueTypeF32:
- g.Val = importedG.Val
- case ValueTypeF64:
- g.Val = importedG.Val
- case ValueTypeV128:
- g.Val, g.ValHi = importedG.Val, importedG.ValHi
- case ValueTypeFuncref, ValueTypeExternref:
- g.Val = importedG.Val
- }
- case OpcodeRefNull:
- switch expr.Data[0] {
- case ValueTypeExternref, ValueTypeFuncref:
- g.Val = 0 // Reference types are opaque 64bit pointer at runtime.
- }
- case OpcodeRefFunc:
- v, _, _ := leb128.LoadUint32(expr.Data)
- g.Val = uint64(funcRefResolver(v))
- case OpcodeVecV128Const:
- g.Val, g.ValHi = binary.LittleEndian.Uint64(expr.Data[0:8]), binary.LittleEndian.Uint64(expr.Data[8:16])
- }
-}
-
-// String implements api.Global.
-func (g *GlobalInstance) String() string {
- switch g.Type.ValType {
- case ValueTypeI32, ValueTypeI64:
- return fmt.Sprintf("global(%d)", g.Val)
- case ValueTypeF32:
- return fmt.Sprintf("global(%f)", api.DecodeF32(g.Val))
- case ValueTypeF64:
- return fmt.Sprintf("global(%f)", api.DecodeF64(g.Val))
- default:
- panic(fmt.Errorf("BUG: unknown value type %X", g.Type.ValType))
- }
-}
-
-func (g *GlobalInstance) Value() (uint64, uint64) {
- if g.Me != nil {
- return g.Me.GetGlobalValue(g.Index)
- }
- return g.Val, g.ValHi
-}
-
-func (g *GlobalInstance) SetValue(lo, hi uint64) {
- if g.Me != nil {
- g.Me.SetGlobalValue(g.Index, lo, hi)
- } else {
- g.Val, g.ValHi = lo, hi
- }
-}
-
-func (s *Store) GetFunctionTypeIDs(ts []FunctionType) ([]FunctionTypeID, error) {
- ret := make([]FunctionTypeID, len(ts))
- for i := range ts {
- t := &ts[i]
- inst, err := s.GetFunctionTypeID(t)
- if err != nil {
- return nil, err
- }
- ret[i] = inst
- }
- return ret, nil
-}
-
-func (s *Store) GetFunctionTypeID(t *FunctionType) (FunctionTypeID, error) {
- s.mux.RLock()
- key := t.key()
- id, ok := s.typeIDs[key]
- s.mux.RUnlock()
- if !ok {
- s.mux.Lock()
- defer s.mux.Unlock()
- // Check again in case another goroutine has already added the type.
- if id, ok = s.typeIDs[key]; ok {
- return id, nil
- }
- l := len(s.typeIDs)
- if uint32(l) >= s.functionMaxTypes {
- return 0, fmt.Errorf("too many function types in a store")
- }
- id = FunctionTypeID(l)
- s.typeIDs[key] = id
- }
- return id, nil
-}
-
-// CloseWithExitCode implements the same method as documented on wazero.Runtime.
-func (s *Store) CloseWithExitCode(ctx context.Context, exitCode uint32) error {
- s.mux.Lock()
- defer s.mux.Unlock()
- // Close modules in reverse initialization order.
- var errs []error
- for m := s.moduleList; m != nil; m = m.next {
- // If closing this module errs, proceed anyway to close the others.
- if err := m.closeWithExitCode(ctx, exitCode); err != nil {
- errs = append(errs, err)
- }
- }
- s.moduleList = nil
- s.nameToModule = nil
- s.nameToModuleCap = 0
- s.typeIDs = nil
- return errors.Join(errs...)
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go
deleted file mode 100644
index ede3047de..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/store_module_list.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package wasm
-
-import (
- "errors"
- "fmt"
-)
-
-// deleteModule makes the moduleName available for instantiation again.
-func (s *Store) deleteModule(m *ModuleInstance) error {
- s.mux.Lock()
- defer s.mux.Unlock()
-
- // Remove this module name.
- if m.prev != nil {
- m.prev.next = m.next
- }
- if m.next != nil {
- m.next.prev = m.prev
- }
- if s.moduleList == m {
- s.moduleList = m.next
- }
- // Clear the m state so it does not enter any other branch
- // on subsequent calls to deleteModule.
- m.prev = nil
- m.next = nil
-
- if m.ModuleName != "" {
- delete(s.nameToModule, m.ModuleName)
-
- // Shrink the map if it's allocated more than twice the size of the list
- newCap := len(s.nameToModule)
- if newCap < nameToModuleShrinkThreshold {
- newCap = nameToModuleShrinkThreshold
- }
- if newCap*2 <= s.nameToModuleCap {
- nameToModule := make(map[string]*ModuleInstance, newCap)
- for k, v := range s.nameToModule {
- nameToModule[k] = v
- }
- s.nameToModule = nameToModule
- s.nameToModuleCap = newCap
- }
- }
- return nil
-}
-
-// module returns the module of the given name or error if not in this store
-func (s *Store) module(moduleName string) (*ModuleInstance, error) {
- s.mux.RLock()
- defer s.mux.RUnlock()
- m, ok := s.nameToModule[moduleName]
- if !ok {
- return nil, fmt.Errorf("module[%s] not instantiated", moduleName)
- }
- return m, nil
-}
-
-// registerModule registers a ModuleInstance into the store.
-// This makes the ModuleInstance visible for import if it's not anonymous, and ensures it is closed when the store is.
-func (s *Store) registerModule(m *ModuleInstance) error {
- s.mux.Lock()
- defer s.mux.Unlock()
-
- if s.nameToModule == nil {
- return errors.New("already closed")
- }
-
- if m.ModuleName != "" {
- if _, ok := s.nameToModule[m.ModuleName]; ok {
- return fmt.Errorf("module[%s] has already been instantiated", m.ModuleName)
- }
- s.nameToModule[m.ModuleName] = m
- if len(s.nameToModule) > s.nameToModuleCap {
- s.nameToModuleCap = len(s.nameToModule)
- }
- }
-
- // Add the newest node to the moduleNamesList as the head.
- m.next = s.moduleList
- if m.next != nil {
- m.next.prev = m
- }
- s.moduleList = m
- return nil
-}
-
-// Module implements wazero.Runtime Module
-func (s *Store) Module(moduleName string) *ModuleInstance {
- m, err := s.module(moduleName)
- if err != nil {
- return nil
- }
- return m
-}
diff --git a/vendor/github.com/tetratelabs/wazero/internal/wasm/table.go b/vendor/github.com/tetratelabs/wazero/internal/wasm/table.go
deleted file mode 100644
index 2123693c6..000000000
--- a/vendor/github.com/tetratelabs/wazero/internal/wasm/table.go
+++ /dev/null
@@ -1,339 +0,0 @@
-package wasm
-
-import (
- "fmt"
- "math"
- "sync"
-
- "github.com/tetratelabs/wazero/api"
- "github.com/tetratelabs/wazero/internal/leb128"
-)
-
-// Table describes the limits of elements and its type in a table.
-type Table struct {
- Min uint32
- Max *uint32
- Type RefType
-}
-
-// RefType is either RefTypeFuncref or RefTypeExternref as of WebAssembly core 2.0.
-type RefType = byte
-
-const (
- // RefTypeFuncref represents a reference to a function.
- RefTypeFuncref = ValueTypeFuncref
- // RefTypeExternref represents a reference to a host object, which is not currently supported in wazero.
- RefTypeExternref = ValueTypeExternref
-)
-
-func RefTypeName(t RefType) (ret string) {
- switch t {
- case RefTypeFuncref:
- ret = "funcref"
- case RefTypeExternref:
- ret = "externref"
- default:
- ret = fmt.Sprintf("unknown(0x%x)", t)
- }
- return
-}
-
-// ElementMode represents a mode of element segment which is either active, passive or declarative.
-//
-// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/syntax/modules.html#element-segments
-type ElementMode = byte
-
-const (
- // ElementModeActive is the mode which requires the runtime to initialize table with the contents in .Init field combined with OffsetExpr.
- ElementModeActive ElementMode = iota
- // ElementModePassive is the mode which doesn't require the runtime to initialize table, and only used with OpcodeTableInitName.
- ElementModePassive
- // ElementModeDeclarative is introduced in reference-types proposal which can be used to declare function indexes used by OpcodeRefFunc.
- ElementModeDeclarative
-)
-
-// ElementSegment are initialization instructions for a TableInstance
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-elem
-type ElementSegment struct {
- // OffsetExpr returns the table element offset to apply to Init indices.
- // Note: This can be validated prior to instantiation unless it includes OpcodeGlobalGet (an imported global).
- OffsetExpr ConstantExpression
-
- // TableIndex is the table's index to which this element segment is applied.
- // Note: This is used if and only if the Mode is active.
- TableIndex Index
-
- // Followings are set/used regardless of the Mode.
-
- // Init indices are (nullable) table elements where each index is the function index by which the module initialize the table.
- Init []Index
-
- // Type holds the type of this element segment, which is the RefType in WebAssembly 2.0.
- Type RefType
-
- // Mode is the mode of this element segment.
- Mode ElementMode
-}
-
-const (
- // ElementInitNullReference represents the null reference in ElementSegment's Init.
- // In Wasm spec, an init item represents either Function's Index or null reference,
- // and in wazero, we limit the maximum number of functions available in a module to
- // MaximumFunctionIndex. Therefore, it is safe to use 1 << 31 to represent the null
- // reference in Element segments.
- ElementInitNullReference Index = 1 << 31
- // elementInitImportedGlobalReferenceType represents an init item which is resolved via an imported global constexpr.
- // The actual function reference stored at Global is only known at instantiation-time, so we set this flag
- // to items of ElementSegment.Init at binary decoding, and unwrap this flag at instantiation to resolve the value.
- //
- // This might collide the init element resolved via ref.func instruction which is resolved with the func index at decoding,
- // but in practice, that is not allowed in wazero thanks to our limit MaximumFunctionIndex. Thus, it is safe to set this flag
- // in init element to indicate as such.
- elementInitImportedGlobalReferenceType Index = 1 << 30
-)
-
-// unwrapElementInitGlobalReference takes an item of the init vector of an ElementSegment,
-// and returns the Global index if it is supposed to get generated from a global.
-// ok is true if the given init item is as such.
-func unwrapElementInitGlobalReference(init Index) (_ Index, ok bool) {
- if init&elementInitImportedGlobalReferenceType == elementInitImportedGlobalReferenceType {
- return init &^ elementInitImportedGlobalReferenceType, true
- }
- return init, false
-}
-
-// WrapGlobalIndexAsElementInit wraps the given index as an init item which is resolved via an imported global value.
-// See the comments on elementInitImportedGlobalReferenceType for more details.
-func WrapGlobalIndexAsElementInit(init Index) Index {
- return init | elementInitImportedGlobalReferenceType
-}
-
-// IsActive returns true if the element segment is "active" mode which requires the runtime to initialize table
-// with the contents in .Init field.
-func (e *ElementSegment) IsActive() bool {
- return e.Mode == ElementModeActive
-}
-
-// TableInstance represents a table of (RefTypeFuncref) elements in a module.
-//
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#table-instances%E2%91%A0
-type TableInstance struct {
- // References holds references whose type is either RefTypeFuncref or RefTypeExternref (unsupported).
- //
- // Currently, only function references are supported.
- References []Reference
-
- // Min is the minimum (function) elements in this table and cannot grow to accommodate ElementSegment.
- Min uint32
-
- // Max if present is the maximum (function) elements in this table, or nil if unbounded.
- Max *uint32
-
- // Type is either RefTypeFuncref or RefTypeExternRef.
- Type RefType
-
- // The following is only used when the table is exported.
-
- // involvingModuleInstances is a set of module instances which are involved in the table instance.
- // This is critical for safety purpose because once a table is imported, it can hold any reference to
- // any function in the owner and importing module instances. Therefore, these module instance,
- // transitively the compiled modules, must be alive as long as the table instance is alive.
- involvingModuleInstances []*ModuleInstance
- // involvingModuleInstancesMutex is a mutex to protect involvingModuleInstances.
- involvingModuleInstancesMutex sync.RWMutex
-}
-
-// ElementInstance represents an element instance in a module.
-//
-// See https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/runtime.html#element-instances
-type ElementInstance = []Reference
-
-// Reference is the runtime representation of RefType which is either RefTypeFuncref or RefTypeExternref.
-type Reference = uintptr
-
-// validateTable ensures any ElementSegment is valid. This caches results via Module.validatedActiveElementSegments.
-// Note: limitsType are validated by decoders, so not re-validated here.
-func (m *Module) validateTable(enabledFeatures api.CoreFeatures, tables []Table, maximumTableIndex uint32) error {
- if len(tables) > int(maximumTableIndex) {
- return fmt.Errorf("too many tables in a module: %d given with limit %d", len(tables), maximumTableIndex)
- }
-
- importedTableCount := m.ImportTableCount
-
- // Create bounds checks as these can err prior to instantiation
- funcCount := m.ImportFunctionCount + m.SectionElementCount(SectionIDFunction)
- globalsCount := m.ImportGlobalCount + m.SectionElementCount(SectionIDGlobal)
-
- // Now, we have to figure out which table elements can be resolved before instantiation and also fail early if there
- // are any imported globals that are known to be invalid by their declarations.
- for i := range m.ElementSection {
- elem := &m.ElementSection[i]
- idx := Index(i)
- initCount := uint32(len(elem.Init))
-
- // Any offset applied is to the element, not the function index: validate here if the funcidx is sound.
- for ei, init := range elem.Init {
- if init == ElementInitNullReference {
- continue
- }
- index, ok := unwrapElementInitGlobalReference(init)
- if ok {
- if index >= globalsCount {
- return fmt.Errorf("%s[%d].init[%d] global index %d out of range", SectionIDName(SectionIDElement), idx, ei, index)
- }
- } else {
- if elem.Type == RefTypeExternref {
- return fmt.Errorf("%s[%d].init[%d] must be ref.null but was %d", SectionIDName(SectionIDElement), idx, ei, init)
- }
- if index >= funcCount {
- return fmt.Errorf("%s[%d].init[%d] func index %d out of range", SectionIDName(SectionIDElement), idx, ei, index)
- }
- }
- }
-
- if elem.IsActive() {
- if len(tables) <= int(elem.TableIndex) {
- return fmt.Errorf("unknown table %d as active element target", elem.TableIndex)
- }
-
- t := tables[elem.TableIndex]
- if t.Type != elem.Type {
- return fmt.Errorf("element type mismatch: table has %s but element has %s",
- RefTypeName(t.Type), RefTypeName(elem.Type),
- )
- }
-
- // global.get needs to be discovered during initialization
- oc := elem.OffsetExpr.Opcode
- if oc == OpcodeGlobalGet {
- globalIdx, _, err := leb128.LoadUint32(elem.OffsetExpr.Data)
- if err != nil {
- return fmt.Errorf("%s[%d] couldn't read global.get parameter: %w", SectionIDName(SectionIDElement), idx, err)
- } else if err = m.verifyImportGlobalI32(SectionIDElement, idx, globalIdx); err != nil {
- return err
- }
- } else if oc == OpcodeI32Const {
- // Per https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 we must pass if imported
- // table has set its min=0. Per https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142, we
- // have to do fail if module-defined min=0.
- if !enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) && elem.TableIndex >= importedTableCount {
- // Treat constants as signed as their interpretation is not yet known per /RATIONALE.md
- o, _, err := leb128.LoadInt32(elem.OffsetExpr.Data)
- if err != nil {
- return fmt.Errorf("%s[%d] couldn't read i32.const parameter: %w", SectionIDName(SectionIDElement), idx, err)
- }
- offset := Index(o)
- if err = checkSegmentBounds(t.Min, uint64(initCount)+uint64(offset), idx); err != nil {
- return err
- }
- }
- } else {
- return fmt.Errorf("%s[%d] has an invalid const expression: %s", SectionIDName(SectionIDElement), idx, InstructionName(oc))
- }
- }
- }
- return nil
-}
-
-// buildTable returns TableInstances if the module defines or imports a table.
-// - importedTables: returned as `tables` unmodified.
-// - importedGlobals: include all instantiated, imported globals.
-//
-// If the result `init` is non-nil, it is the `tableInit` parameter of Engine.NewModuleEngine.
-//
-// Note: An error is only possible when an ElementSegment.OffsetExpr is out of range of the TableInstance.Min.
-func (m *ModuleInstance) buildTables(module *Module, skipBoundCheck bool) (err error) {
- idx := module.ImportTableCount
- for i := range module.TableSection {
- tsec := &module.TableSection[i]
- // The module defining the table is the one that sets its Min/Max etc.
- m.Tables[idx] = &TableInstance{
- References: make([]Reference, tsec.Min), Min: tsec.Min, Max: tsec.Max,
- Type: tsec.Type,
- }
- idx++
- }
-
- if !skipBoundCheck {
- for elemI := range module.ElementSection { // Do not loop over the value since elementSegments is a slice of value.
- elem := &module.ElementSection[elemI]
- table := m.Tables[elem.TableIndex]
- var offset uint32
- if elem.OffsetExpr.Opcode == OpcodeGlobalGet {
- // Ignore error as it's already validated.
- globalIdx, _, _ := leb128.LoadUint32(elem.OffsetExpr.Data)
- global := m.Globals[globalIdx]
- offset = uint32(global.Val)
- } else { // i32.const
- // Ignore error as it's already validated.
- o, _, _ := leb128.LoadInt32(elem.OffsetExpr.Data)
- offset = uint32(o)
- }
-
- // Check to see if we are out-of-bounds
- initCount := uint64(len(elem.Init))
- if err = checkSegmentBounds(table.Min, uint64(offset)+initCount, Index(elemI)); err != nil {
- return
- }
- }
- }
- return
-}
-
-// checkSegmentBounds fails if the capacity needed for an ElementSegment.Init is larger than limitsType.Min
-//
-// WebAssembly 1.0 (20191205) doesn't forbid growing to accommodate element segments, and spectests are inconsistent.
-// For example, the spectests enforce elements within Table limitsType.Min, but ignore Import.DescTable min. What this
-// means is we have to delay offset checks on imported tables until we link to them.
-// e.g. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 wants pass on min=0 for import
-// e.g. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142 wants fail on min=0 module-defined
-func checkSegmentBounds(min uint32, requireMin uint64, idx Index) error { // uint64 in case offset was set to -1
- if requireMin > uint64(min) {
- return fmt.Errorf("%s[%d].init exceeds min table size", SectionIDName(SectionIDElement), idx)
- }
- return nil
-}
-
-func (m *Module) verifyImportGlobalI32(sectionID SectionID, sectionIdx Index, idx uint32) error {
- ig := uint32(math.MaxUint32) // +1 == 0
- for i := range m.ImportSection {
- imp := &m.ImportSection[i]
- if imp.Type == ExternTypeGlobal {
- ig++
- if ig == idx {
- if imp.DescGlobal.ValType != ValueTypeI32 {
- return fmt.Errorf("%s[%d] (global.get %d): import[%d].global.ValType != i32", SectionIDName(sectionID), sectionIdx, idx, i)
- }
- return nil
- }
- }
- }
- return fmt.Errorf("%s[%d] (global.get %d): out of range of imported globals", SectionIDName(sectionID), sectionIdx, idx)
-}
-
-// Grow appends the `initialRef` by `delta` times into the References slice.
-// Returns -1 if the operation is not valid, otherwise the old length of the table.
-//
-// https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/exec/instructions.html#xref-syntax-instructions-syntax-instr-table-mathsf-table-grow-x
-func (t *TableInstance) Grow(delta uint32, initialRef Reference) (currentLen uint32) {
- currentLen = uint32(len(t.References))
- if delta == 0 {
- return
- }
-
- if newLen := int64(currentLen) + int64(delta); // adding as 64bit ints to avoid overflow.
- newLen >= math.MaxUint32 || (t.Max != nil && newLen > int64(*t.Max)) {
- return 0xffffffff // = -1 in signed 32-bit integer.
- }
- t.References = append(t.References, make([]uintptr, delta)...)
-
- // Uses the copy trick for faster filling the new region with the initial value.
- // https://gist.github.com/taylorza/df2f89d5f9ab3ffd06865062a4cf015d
- newRegion := t.References[currentLen:]
- newRegion[0] = initialRef
- for i := 1; i < len(newRegion); i *= 2 {
- copy(newRegion[i:], newRegion[:i])
- }
- return
-}