codegen

package
v0.5.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

Package codegen translates a parsed wasm Module into a single Go source file printed via go/format.

Package codegen — wasip1_native.go owns the default wasi_snapshot_preview1 host implementation that gets woven into the translated output.

Design notes:

  • The struct WasiStubs holds all the runtime-side state (fd table, args, env, monotonic start) so the wasm runtime's Module type stays free of host-specific fields.
  • DefaultWASI() returns *WasiStubs wired to os.Stdin/Stdout/Stderr, os.Args, os.Environ() and time.Now() — drop-in replacement for the wazero wasi_snapshot_preview1 interceptor.
  • Memory access uses m.memory (lowercase) at template time. In multi-package mode, capitalizeModuleFieldRefs rewrites it to m.Memory so the impl works in base/ too.
  • Method signatures must match what t.importMethodName produces from the wasm import names. We use the same MangleID + capitalize chain by emitting the exact wasi function names ("Environ_get" etc).
  • Bodies favour clarity over micro-optimisation.

Security model: WasiStubs is a faithful Go-syscall passthrough for the translated module. There is no sandbox, no path-traversal refuse logic, and no allow-list — the translated module has the same filesystem, clock, environment, and stdio access as the host Go process that links it in. Out-of-range linear-memory accesses are reported back to the guest as EFAULT (rather than being allowed to panic the host) because wasm itself traps on OOB; that's the only "refusal" the stubs perform. Callers that need a tighter sandbox should pass their own Wasi_snapshot_preview1Imports implementation via NewWithWASI.

File layout: this file is real, compilable Go and is also //go:embed-ed so the same code that the codegen test suite exercises is the code that gets written into generated output. Everything goes through the Go stdlib (os, time, syscall, net) so no per-platform companion files or third-party dependencies are needed.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExportMethodName

func ExportMethodName(name string) string

ExportMethodName returns the Go method name for a wasm export. The algorithm preserves underscores between numeric segments so names like `w_56_10` and `w_561_0` (which collide if underscores are stripped) stay distinct as `W_56_10` and `W_561_0`. Letter-bordered underscores are dropped and CamelCased — `wasm_alloc` → `WasmAlloc`. Always starts with an uppercase letter so the method is exported.

func MangleID

func MangleID(name string) string

MangleID returns a valid Go identifier derived from the given wasm name. Empty input becomes "_". A leading digit is prefixed with "_". Any rune outside [A-Za-z0-9_] is encoded as "_x{hex}". Go keywords get a trailing underscore.

func MangleModuleField

func MangleModuleField(name string) string

MangleModuleField returns the Go struct-field name for an imported module (e.g. "wasi_snapshot_preview1" -> "wasi_snapshot_preview1").

func MangleModuleType

func MangleModuleType(name string) string

MangleModuleType returns the Go type name used for the interface that represents an imported module (e.g. "env" -> "envImports").

func SetMultiPackageThreshold added in v0.1.2

func SetMultiPackageThreshold(b int) func()

SetMultiPackageThreshold overrides the auto-multi-package decision threshold to b bytes for the rest of the current process. Pass 0 to always select the multi-package + linkname-split layout regardless of wasm size; pass -1 to restore the default (auto-derived from wasm size). The returned closure restores the previous value and should be invoked via defer:

defer codegen.SetMultiPackageThreshold(0)()

The defaults are auto-derived and most callers should not touch this. The override is supported for diagnostics, build-time memory tuning, and exercising the multi-package path on small fixtures in tests.

Types

type DirectAsmExcLayout added in v0.5.4

type DirectAsmExcLayout struct {
	Pending int // excPending int32
	Tag     int // excTag uint32
	Vals    int // excVals [excSlots]uint64 (base of slot 0)
}

DirectAsmExcLayout is the byte offset of each exception-state field within the generated Module struct (see Result.DirectAsmExc).

type DirectAsmFn added in v0.5.0

type DirectAsmFn struct {
	Fn           *ssa.Func
	Sig          wasm.FuncType
	Packed       bool
	PackedParams []ssa.Type
	// Windows lists the fused windows the emission-time fusion pass
	// claimed inside this function, so the asm bundle can emit the
	// shared fused splice bodies instead of per-op splices. Recorded
	// only when every member, root and parameter source is nameable
	// in the retained SSA (see addDirectAsmWindow).
	Windows []DirectAsmWindow
}

DirectAsmFn is a function retained for direct-asm emission: its finalized SSA (post optimization fixpoint, idiom rewrites, and outlining) plus the wasm-typed signature the asm frame layout needs. Packed marks the outlined packed-boundary form: the Go-side signature carries only the module pointer (Sig is then results-only) and the parameter values ride the Module's outline-pack scratch, PackedParams giving their SSA types in slot order (v128 = two slots).

type DirectAsmParamSrc added in v0.5.4

type DirectAsmParamSrc struct {
	IsConst bool
	Const   int64
	Val     *ssa.Value
	ArgIdx  int
}

DirectAsmParamSrc is one fused-signature parameter's source in the retained SSA: a compile-time constant staged as an immediate, or a member value's argument (Val.Args[ArgIdx]).

type DirectAsmWindow added in v0.5.4

type DirectAsmWindow struct {
	Tree      *simdfuse.Tree
	Members   []*ssa.Value
	Roots     []*ssa.Value
	ScalarSrc []DirectAsmParamSrc
	FloatSrc  []DirectAsmParamSrc
	PairSrc   []DirectAsmParamSrc
}

DirectAsmWindow describes one fused window inside a retained function: the interned tree, the member call values it replaces (scheduled order), the root values per Tree.RootList(), and the fused signature's parameter sources. The asm bundle stages the signature from the sources and emits the shared fused splice body in place of the members' per-op splices.

type FS added in v0.3.0

type FS interface {
	// OpenFile mirrors os.OpenFile: flag is O_RDONLY/O_WRONLY/O_RDWR optionally
	// OR'd with O_CREATE/O_EXCL/O_TRUNC/O_APPEND. The returned File must
	// support the operations the mode implies.
	OpenFile(name string, flag int, perm os.FileMode) (File, error)
	Mkdir(name string, perm os.FileMode) error
	Remove(name string) error
	Rename(oldName, newName string) error
	Stat(name string) (os.FileInfo, error)
	Lstat(name string) (os.FileInfo, error)
	Symlink(oldName, newName string) error
	Readlink(name string) (string, error)
	Link(oldName, newName string) error
}

FS is the read/write filesystem backend the WASI host opens files through. It abstracts the default os-backed filesystem so an embedder can supply an alternative — an in-memory FS, an overlay, a read-only bundle, ... — and have every guest path operation (open, stat, mkdir, readdir, write, ...) routed to it. It is a write-capable superset of io/fs.FS.

Names are GUEST paths relative to the preopen root: slash-separated, with no leading slash (e.g. "encodings/__init__.py", or "" for the root). Methods should return the standard fs errors (fs.ErrNotExist, fs.ErrExist, fs.ErrPermission) so the host maps them to the right wasi errno.

type File added in v0.3.0

type File interface {
	Read(p []byte) (int, error)
	ReadAt(p []byte, off int64) (int, error)
	Write(p []byte) (int, error)
	WriteAt(p []byte, off int64) (int, error)
	Seek(offset int64, whence int) (int64, error)
	Close() error
	Stat() (os.FileInfo, error)
	ReadDir(n int) ([]os.DirEntry, error)
	Sync() error
	Truncate(size int64) error
	Name() string
}

File is an open file handle returned by FS.OpenFile. *os.File satisfies it, so the default os backend needs no wrapper.

type MemFS added in v0.3.0

type MemFS struct {
	// contains filtered or unexported fields
}

MemFS is an in-memory read/write FS. Each value is an independent tree, so two interpreters given separate MemFS values cannot observe each other's files (full per-interpreter filesystem isolation, no disk). Build one with NewMemFS. Safe for concurrent use.

func NewMemFS added in v0.3.0

func NewMemFS() *MemFS

NewMemFS returns an empty in-memory filesystem with a root directory.

func (*MemFS) Chtimes added in v0.3.0

func (fsys *MemFS) Chtimes(name string, _ time.Time, mtime time.Time) error

Chtimes implements the optional chtimesFS capability.

func (fsys *MemFS) Link(_, _ string) error

func (*MemFS) Lstat added in v0.3.0

func (fsys *MemFS) Lstat(name string) (os.FileInfo, error)

func (*MemFS) Mkdir added in v0.3.0

func (fsys *MemFS) Mkdir(name string, perm os.FileMode) error

func (*MemFS) MkdirAll added in v0.3.0

func (fsys *MemFS) MkdirAll(name string, perm os.FileMode) error

MkdirAll creates name and any missing parents. Exposed so embedders can populate the FS (e.g. unpack a stdlib bundle) before handing it to a module.

func (*MemFS) OpenFile added in v0.3.0

func (fsys *MemFS) OpenFile(name string, flag int, perm os.FileMode) (File, error)
func (fsys *MemFS) Readlink(name string) (string, error)

func (*MemFS) Remove added in v0.3.0

func (fsys *MemFS) Remove(name string) error

func (*MemFS) Rename added in v0.3.0

func (fsys *MemFS) Rename(oldName, newName string) error

func (*MemFS) Stat added in v0.3.0

func (fsys *MemFS) Stat(name string) (os.FileInfo, error)
func (fsys *MemFS) Symlink(_, _ string) error

memfs has no symlinks/hardlinks.

func (*MemFS) WriteFile added in v0.3.0

func (fsys *MemFS) WriteFile(name string, data []byte, perm os.FileMode) error

WriteFile creates (or overwrites) a file with data, making parent dirs as needed. Exposed for pre-populating the FS.

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module is the minimal in-package proxy for the generated module type. In production, codegen emits a separate Module struct into the user's output package; this in-package Module exists so the WasiStubs methods below are real, compilable Go (and therefore directly testable). The embedded-source path strips the package + import header at emit time and lets the generated Module shadow this one.

type MultiPackageChunk

type MultiPackageChunk struct {
	FuncIdxs []uint32
	Bytes    int
}

MultiPackageChunk lists the function indices owned by a single chunk package, plus the size estimate used during packing.

type MultiPackagePlan

type MultiPackagePlan struct {
	// Chunks in topological order. Chunks[0] has no chunk dependencies;
	// Chunks[i] (i>0) depends on Chunks[0..i-1] via Go imports.
	Chunks []MultiPackageChunk
	// FuncToChunk maps a defined-function index (NumImportedFuncs..end) to
	// the chunk index that holds it.
	FuncToChunk map[uint32]int
}

MultiPackagePlan describes how the defined wasm functions are distributed across a chain of Go packages. Each chunk imports all earlier chunks so the Go build system compiles them strictly serially — bounding peak compiler memory to one chunk's SSA cost regardless of total module size.

func PlanLinknamePackages

func PlanLinknamePackages(mod *wasm.Module, chunkBytes int, reachable map[uint32]bool) (*MultiPackagePlan, error)

PlanLinknamePackages builds a chunk plan for the linkname-split layout (Options.LinknameSplit = true). Mutually-recursive functions are still kept in the same SCC (so they don't have to pay a linkname hop to call each other), but the SCC-level topological order is NOT used to bound chunk dependencies — cross-chunk calls are wired by //go:linkname at emit time, so chunks can call any other chunk regardless of ordering. The partitioner uses first-fit-decreasing bin packing on SCC byte size to balance chunks without the "later chunks must only call earlier ones" constraint. PlanLinknamePackages builds the chunk plan for linkname-split mode. reachable, when non-nil, is the whole-function dead-code-elimination result keyed by local index; SCCs whose functions are all dead are skipped so they neither consume chunk budget nor get emitted.

type Options

type Options struct {
	// Package is the Go package name to emit. Required.
	Package string
	// OutputImportPath is the Go import path the generated package
	// lives at — e.g. "example.com/myproj/internal/wasm". Required
	// for every Translate call. In single-file mode the path is the
	// package's own import path; in the auto-multi-package layout it
	// is used as the base import for the chained sub-packages
	// (<path>/base, <path>/p0, <path>/p1, ...).
	OutputImportPath string
	// BulkExportPrefix opts a subset of exports into a compact
	// dispatch shape. Exports whose names match `<prefix><svc>_<mt>`
	// (svc and mt decimal integers) are emitted as standalone
	// `Inv_<svc>_<mt>` functions so the Go linker can prune unused
	// ones. Exports that do not match the prefix get the usual
	// per-export method. An empty prefix disables bulk dispatch.
	BulkExportPrefix string
	// EntryExports narrows the export root set for whole-function
	// dead-code elimination.
	//
	//   - nil: every export is a DCE root.
	//   - empty slice (non-nil, length 0): no export is a root; only
	//     start + table-installed functions + reachable calls survive.
	//   - non-empty: only the named exports are roots (others may
	//     still survive via the table or transitive calls).
	EntryExports []string
	// KeepDeadFuncs disables whole-function dead-code elimination.
	// Useful for diffing / debugging.
	KeepDeadFuncs bool
	// PromotionReportPath, when non-empty, writes the SSA memory-
	// promotion report (JSON: per-function frame/rodata/slab
	// classification) to this path.
	PromotionReportPath string
	// PureOnly emits the pure-Go backend only: function bodies are
	// written without the `!amd64 && !arm64` build gate (so they compile
	// on every GOARCH) and the caller (transpile.Translate) skips the
	// gcasm asm bundle entirely. The result is ABIInternal everywhere —
	// slower to compile / heavier on tooling for large modules, but the
	// reference backend for benchmarking codegen quality without the
	// gcasm ABI0 marshalling.
	PureOnly bool

	// OutlineMinValues enables outlining of large loops into their own
	// functions and sets the minimum loop body size (in SSA values)
	// worth extracting. 0 disables outlining. Modules whose hot
	// functions exceed gc's pattern-matching appetite (kernel-library-sized)
	// want a low threshold like 100; small modules gain nothing.
	OutlineMinValues int
	// SIMDUnroll unrolls eligible SIMD loops by this factor before
	// scalarization, with exact trip routing. 0 disables.
	SIMDUnroll int
	// FuseLoops fuses whole countdown loops around fused SIMD regions
	// into single asm splices; FuseLoopUnroll adds an in-splice unroll
	// lane by that factor (0 = no in-splice unroll).
	FuseLoops      bool
	FuseLoopUnroll int
	// DisableF16Table opts out of the f16-table-keyed rewrites.
	// Tables are verified automatically — statically when the data
	// image holds the IEEE map, otherwise by detecting the module's
	// own initialization loop (full-range constant-strided store
	// coverage) — so there is no address to configure; this switch
	// exists only to disable the rewrites outright.
	DisableF16Table bool
	// FastMath opts asm splice synthesis out of wasm bit-exactness:
	// SDOT lane grouping without the TBL permutation, fused
	// multiply-adds, dual accumulators, and the SMMLA tile kernel for
	// paired q8_0 rows. The output no longer matches the wasm program
	// bit for bit (like a native build vs the wasm), so integrators
	// gate it and validate with token-level equivalence instead of
	// byte-equality probes.
	FastMath bool
	// VecDotPairEntry opts into vec_dot row/column pairing: it names
	// the per-type trait-table entry (the source runtime's type-enum
	// value) whose self-dot should run two rows and columns per call
	// (see the nrc2 recognizer's package comment for the verified
	// structural contract). Zero — the default — disables the scan
	// and leaves every module untouched.
	VecDotPairEntry int
	// VecDotRows additionally batches the verified vec_dot's caller
	// row loops: the translator emits a row-looped companion of the
	// verified function and rewrites matching driver loops into one
	// guarded companion call per chunk (the original loop stays as
	// the guard-miss branch, so semantics are preserved for every
	// runtime type). Requires VecDotPairEntry; off by default and
	// inert without it.
	VecDotRows bool
	// FuseDebug prints SIMD fusion diagnostics to stderr: failed
	// window-trial refusals and loop-upgrade rejections, tagged by
	// the refusing check. Diagnosis only; no effect on output.
	FuseDebug bool
	// DirectAsmFuncs names functions (post-rename FnN / fnN symbols,
	// or outlined-loop names like Fn1016l13807) whose finalized SSA
	// should be retained in Result.DirectAsmSSA for the asm bundle to
	// emit directly via internal/asmgen instead of transforming the
	// gc-captured listing. Retention is opt-in per function; a name
	// the direct emitter cannot handle later falls back to the normal
	// transform path, so listing a function here never breaks the
	// build. Empty disables retention entirely.
	DirectAsmFuncs []string
}

Options controls code generation.

Several previously-public knobs (DataSidecar, MultiPackage, MultiPackageBaseImport, MultiPackageChunkBytes, LinknameSplit, NativeWASI, UseSSA, PerExportDispatch) are now auto-derived:

  • SSA lowering, the data sidecar layout, and native wasip1 are always on. They are the only supported configuration; if SSA cannot lower a function, Translate fails with a clear error identifying the function index and the offending opcode.
  • Multi-package + linkname-split is selected automatically when the sum of wasm function-body bytes exceeds the internal 1 MiB threshold; below that threshold a single Go file is emitted.
  • Per-export dispatch is auto-on whenever BulkExportPrefix is set (no remaining caller wanted the consolidated InvokeExport switch — that form is gone).

type OutlinedSig added in v0.5.0

type OutlinedSig struct {
	Params []wasm.ValType
	Result *wasm.ValType // nil when the function returns nothing
	// Packed: the boundary exceeds the register ABI, so the caller
	// passes one pointer to a [len(Params)]uint64 slot array instead
	// of individual scalar arguments.
	Packed bool
}

OutlinedSig is an extracted function's signature in wasm value types, for the asm bundle to transform its body like a regular translated function.

type Result

type Result struct {
	// Sidecars maps base filenames (e.g. "data0.bin") to raw byte contents.
	// Populated when Options.DataSidecar is true.
	Sidecars map[string][]byte
	// Files maps relative output path → contents. Populated only when
	// Options.MultiPackage is true; otherwise nil. The caller writes each
	// entry to <outDir>/<key>.
	Files map[string][]byte
	// AuxFiles maps relative output path → raw Go source that must be
	// written alongside the main output but NOT routed through //go:embed
	// (unlike Sidecars). The WASI runtime uses this for the per-platform
	// wasip1_native_*.go companions whose //go:build tags are load-bearing.
	AuxFiles map[string][]byte
	// FusedLoops maps synthetic fused-LOOP helper names to their loop
	// descriptors.
	FusedLoops map[string]*simdfuse.Loop
	// FusedSimd maps synthetic fused-SIMD helper names to their region
	// descriptors, for the gcasm backend to synthesize inline bodies
	// from. Nil when the scalarizer fused nothing. See internal/simdfuse.
	FusedSimd map[string]*simdfuse.Tree
	// Outlined maps chunk dir ("" single-package) to the names of loop
	// functions extracted there (see internal/ssa/outline.go). The asm
	// bundle keeps their pure-Go bodies on every GOARCH.
	Outlined map[string][]string
	// Nrc2VecDot / Nrc2Companion name the paired vec_dot and its
	// paired-tile companion when the row/column pairing rewrite fired
	// (see nrc2.go); empty when off. The asm bundle may retarget the
	// fast-math feature body's companion call to a native tile kernel.
	Nrc2VecDot    string
	Nrc2Companion string
	// OutlinedSigs maps each extracted function name to its signature,
	// letting the asm bundle transform its body like a translated
	// function.
	OutlinedSigs map[string]OutlinedSig
	// DirectAsmSSA maps function names listed in Options.DirectAsmFuncs
	// to their retained finalized SSA, for the asm bundle to emit via
	// internal/asmgen. Names the translator never saw (or whose SSA is
	// ineligible for retention) are simply absent.
	DirectAsmSSA map[string]DirectAsmFn
	// DirectAsmGlobals is the byte offset of each wasm global within
	// the generated Module struct (-1 for imported globals), for
	// direct-asm bodies to inline global accesses. Nil unless
	// direct-asm retention is active. The generated bundle carries
	// compile-time assertions pinning these offsets.
	DirectAsmGlobals []int
	// DirectAsmExc is the byte offset of each exception-state field
	// within the generated Module struct, for direct-asm bodies to
	// inline OpExc* accesses. Nil unless direct-asm retention is
	// active and the module has exception state. Pinned by the same
	// generated compile-time assertions as DirectAsmGlobals.
	DirectAsmExc *DirectAsmExcLayout
}

Result returns auxiliary outputs from Translate beyond the main Go source.

func Translate

func Translate(w io.Writer, m *wasm.Module, opts Options) (Result, error)

Translate parses helpers, walks the module, and emits Go source for module m. When the wasm module's function-body total fits in the internal single-file budget, source is written to w and Result.Files is nil. When the budget is exceeded, w is unused and Result.Files holds the multi-package chain (relative path → bytes) the caller must write to disk under the directory that maps to opts.OutputImportPath.

Required options: opts.Package and opts.OutputImportPath. Any other configuration (SSA, sidecar layout, native wasip1, multi-package, linkname-split, per-export dispatch) is auto-derived.

EntryExports narrows the whole-function DCE root set; see the Options.EntryExports doc comment for the empty-slice vs nil distinction.

type WasiExitError

type WasiExitError struct{ Code int32 }

WasiExitError is the sentinel that the recover layer of SafeInvokeExport promotes Proc_exit() panics into, so a wasm-level exit doesn't kill the host process and the caller can read the exit code instead.

func (*WasiExitError) Error

func (e *WasiExitError) Error() string

type WasiStubs

type WasiStubs struct {
	// contains filtered or unexported fields
}

WasiStubs is the default Go-native implementation of wasi_snapshot_preview1. State is owned per-Module via NewWithWASI / DefaultWASI.

func DefaultWASI

func DefaultWASI() *WasiStubs

DefaultWASI returns a WasiStubs configured for typical CLI use: real stdio, os.Args, os.Environ(), wall + monotonic clocks. Consumers who want a sandboxed setup should construct their own WasiStubs (or any Wasi_snapshot_preview1Imports implementation) and pass it to NewWithWASI.

func (*WasiStubs) Args_get

func (w *WasiStubs) Args_get(m *Module, argv, argvBuf int32) int32

func (*WasiStubs) Args_get64 added in v0.5.0

func (w *WasiStubs) Args_get64(m *Module, argv, argvBuf int64) int32

func (*WasiStubs) Args_sizes_get

func (w *WasiStubs) Args_sizes_get(m *Module, argcPtr, argvBufLenPtr int32) int32

func (*WasiStubs) Args_sizes_get64 added in v0.5.0

func (w *WasiStubs) Args_sizes_get64(m *Module, argcPtr, argvBufLenPtr int64) int32

func (*WasiStubs) Clock_res_get

func (w *WasiStubs) Clock_res_get(m *Module, clockID int32, resPtr int32) int32

func (*WasiStubs) Clock_time_get

func (w *WasiStubs) Clock_time_get(m *Module, clockID int32, precision int64, timePtr int32) int32

func (*WasiStubs) Clock_time_get64 added in v0.5.0

func (w *WasiStubs) Clock_time_get64(m *Module, clockID int64, precision int64, timePtr int64) int32

func (*WasiStubs) Environ_get

func (w *WasiStubs) Environ_get(m *Module, envv, envBuf int32) int32

func (*WasiStubs) Environ_get64 added in v0.5.0

func (w *WasiStubs) Environ_get64(m *Module, envv, envBuf int64) int32

func (*WasiStubs) Environ_sizes_get

func (w *WasiStubs) Environ_sizes_get(m *Module, envcPtr, envBufLenPtr int32) int32

func (*WasiStubs) Environ_sizes_get64 added in v0.5.0

func (w *WasiStubs) Environ_sizes_get64(m *Module, envcPtr, envBufLenPtr int64) int32

func (*WasiStubs) Fd_advise

func (w *WasiStubs) Fd_advise(m *Module, fd int32, offset, length int64, advice int32) int32

func (*WasiStubs) Fd_allocate

func (w *WasiStubs) Fd_allocate(m *Module, fd int32, offset, length int64) int32

func (*WasiStubs) Fd_close

func (w *WasiStubs) Fd_close(m *Module, fd int32) int32

func (*WasiStubs) Fd_close64 added in v0.5.0

func (w *WasiStubs) Fd_close64(m *Module, fd int64) int32

func (*WasiStubs) Fd_datasync

func (w *WasiStubs) Fd_datasync(m *Module, fd int32) int32

func (*WasiStubs) Fd_fdstat_get

func (w *WasiStubs) Fd_fdstat_get(m *Module, fd, ptr int32) int32

func (*WasiStubs) Fd_fdstat_get64 added in v0.5.0

func (w *WasiStubs) Fd_fdstat_get64(m *Module, fd int64, ptr int64) int32

func (*WasiStubs) Fd_fdstat_set_flags

func (w *WasiStubs) Fd_fdstat_set_flags(m *Module, fd, flags int32) int32

Fd_fdstat_set_flags maps WASI fdflags to OS file-status flags via the per-platform Fcntl wrapper. The flags are also cached on the wasiOpen so a subsequent Fd_fdstat_get reflects what the guest set. Stdio fds store the requested flags but otherwise no-op; sockets/listeners take only the cache update because Go's net layer manages blocking mode internally.

func (*WasiStubs) Fd_fdstat_set_flags64 added in v0.5.0

func (w *WasiStubs) Fd_fdstat_set_flags64(m *Module, fd, flags int64) int32

func (*WasiStubs) Fd_fdstat_set_rights

func (w *WasiStubs) Fd_fdstat_set_rights(m *Module, fd int32, rightsBase, rightsInherit int64) int32

Fd_fdstat_set_rights stores the requested rights on the wasiOpen but does not enforce them — the host process is the trust boundary. WASI programs that succeed with maximal rights (per Fd_fdstat_get) get the same ESUCCESS here.

func (*WasiStubs) Fd_filestat_get

func (w *WasiStubs) Fd_filestat_get(m *Module, fd, ptr int32) int32

func (*WasiStubs) Fd_filestat_set_size

func (w *WasiStubs) Fd_filestat_set_size(m *Module, fd int32, size int64) int32

func (*WasiStubs) Fd_filestat_set_times

func (w *WasiStubs) Fd_filestat_set_times(m *Module, fd int32, atim, mtim int64, fstFlags int32) int32

func (*WasiStubs) Fd_pread

func (w *WasiStubs) Fd_pread(m *Module, fd, iovs, iovsLen int32, offset int64, nreadPtr int32) int32

func (*WasiStubs) Fd_prestat_dir_name

func (w *WasiStubs) Fd_prestat_dir_name(m *Module, fd, buf, buflen int32) int32

func (*WasiStubs) Fd_prestat_dir_name64 added in v0.5.0

func (w *WasiStubs) Fd_prestat_dir_name64(m *Module, fd, buf, buflen int64) int32

func (*WasiStubs) Fd_prestat_get

func (w *WasiStubs) Fd_prestat_get(m *Module, fd, ptr int32) int32

func (*WasiStubs) Fd_prestat_get64 added in v0.5.0

func (w *WasiStubs) Fd_prestat_get64(m *Module, fd, ptr int64) int32

func (*WasiStubs) Fd_pwrite

func (w *WasiStubs) Fd_pwrite(m *Module, fd, iovs, iovsLen int32, offset int64, nwrittenPtr int32) int32

func (*WasiStubs) Fd_read

func (w *WasiStubs) Fd_read(m *Module, fd, iovs, iovsLen, nreadPtr int32) int32

func (*WasiStubs) Fd_read64 added in v0.5.0

func (w *WasiStubs) Fd_read64(m *Module, fd, iovs, iovsLen, nreadPtr int64) int32

func (*WasiStubs) Fd_readdir

func (w *WasiStubs) Fd_readdir(m *Module, fd, buf, buflen int32, cookie int64, bufusedPtr int32) int32

func (*WasiStubs) Fd_readdir64 added in v0.5.0

func (w *WasiStubs) Fd_readdir64(m *Module, fd, buf, buflen, cookie, bufusedPtr int64) int32

func (*WasiStubs) Fd_renumber

func (w *WasiStubs) Fd_renumber(m *Module, from, to int32) int32

func (*WasiStubs) Fd_seek

func (w *WasiStubs) Fd_seek(m *Module, fd int32, offset int64, whence, newOffPtr int32) int32

func (*WasiStubs) Fd_seek64 added in v0.5.0

func (w *WasiStubs) Fd_seek64(m *Module, fd int64, offset int64, whence int64, newOffPtr int64) int32

func (*WasiStubs) Fd_sync

func (w *WasiStubs) Fd_sync(m *Module, fd int32) int32

func (*WasiStubs) Fd_tell

func (w *WasiStubs) Fd_tell(m *Module, fd, offsetPtr int32) int32

func (*WasiStubs) Fd_write

func (w *WasiStubs) Fd_write(m *Module, fd, iovs, iovsLen, nwrittenPtr int32) int32

func (*WasiStubs) Fd_write64 added in v0.5.0

func (w *WasiStubs) Fd_write64(m *Module, fd int64, iovs int64, iovsLen int64, nwrittenPtr int64) int32

func (*WasiStubs) Path_create_directory

func (w *WasiStubs) Path_create_directory(m *Module, dirFd, pathPtr, pathLen int32) int32

func (*WasiStubs) Path_filestat_get

func (w *WasiStubs) Path_filestat_get(m *Module, dirFd, flags, pathPtr, pathLen, outPtr int32) int32

func (*WasiStubs) Path_filestat_get64 added in v0.5.0

func (w *WasiStubs) Path_filestat_get64(m *Module, dirFd, flags, pathPtr, pathLen, outPtr int64) int32

func (*WasiStubs) Path_filestat_set_times

func (w *WasiStubs) Path_filestat_set_times(m *Module, dirFd, flags, pathPtr, pathLen int32, atim, mtim int64, fstFlags int32) int32
func (w *WasiStubs) Path_link(m *Module, oldFd, oldFlags, oldPathPtr, oldPathLen, newFd, newPathPtr, newPathLen int32) int32

func (*WasiStubs) Path_open

func (w *WasiStubs) Path_open(m *Module, dirFd, dirflags, pathPtr, pathLen, oflags int32, fsRightsBase, fsRightsInherit int64, fdflags, openedFdPtr int32) int32

Path_open opens a wasm-supplied path and registers it in the fd table. The path is resolved against the host filesystem with the same rights the host Go process has — wasm2go's default WASI is a thin passthrough, not a sandbox. The dirFd == 3 special case keeps the "preopen /" convention that wasi-libc requires for its directory enumeration, but the path itself is opened verbatim (joined to "/") using os.OpenFile. Callers that need a sandbox should provide their own Wasi_snapshot_preview1Imports implementation via NewWithWASI.

func (*WasiStubs) Path_open64 added in v0.5.0

func (w *WasiStubs) Path_open64(m *Module, dirFd, dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInherit, fdflags, openedFdPtr int64) int32
func (w *WasiStubs) Path_readlink(m *Module, dirFd, pathPtr, pathLen, buf, buflen, bufusedPtr int32) int32

func (*WasiStubs) Path_remove_directory

func (w *WasiStubs) Path_remove_directory(m *Module, dirFd, pathPtr, pathLen int32) int32

func (*WasiStubs) Path_rename

func (w *WasiStubs) Path_rename(m *Module, oldFd, oldPathPtr, oldPathLen, newFd, newPathPtr, newPathLen int32) int32
func (w *WasiStubs) Path_symlink(m *Module, targetPtr, targetLen, dirFd, linkPathPtr, linkPathLen int32) int32
func (w *WasiStubs) Path_unlink_file(m *Module, dirFd, pathPtr, pathLen int32) int32

func (*WasiStubs) Pipe added in v0.3.0

func (w *WasiStubs) Pipe(m *Module, fdsOutPtr int32) int32

Pipe is a NON-STANDARD host import (module wasi_snapshot_preview1, name "pipe") backing the bridge's pipe()/pipe2(). It creates a host OS pipe and registers both ends as guest fds, writing [readFd, writeFd] (two i32) at fdsOutPtr. The guest reads the read end via Fd_read; the write end is given to a child as its stdout/stderr via Proc_spawn, so subprocess.run can capture output. Returns 0 or a negative errno.

func (*WasiStubs) Poll_oneoff

func (w *WasiStubs) Poll_oneoff(m *Module, inPtr, outPtr, nsubs, neventsPtr int32) int32

Poll_oneoff decodes the WASI subscription_u records and reproduces the requested events.

Each subscription is 48 bytes:

u64 userdata
u8  eventtype  (0=clock, 1=fd_read, 2=fd_write)
... per-type payload starting at offset 16

For clock subscriptions, payload at offset 16 is: u32 clock_id, u64 timeout, u64 precision, u16 sub_clock_flags (bit0=ABSTIME). We sleep for `timeout` ns (relative timer) or the diff to `timeout` (absolute timer). For fd_read / fd_write subscriptions, payload at offset 16 is a u32 fd; we call into the platform Poll helper to wait for readiness.

Each emitted event is 32 bytes: u64 userdata, u16 errno, u16 eventtype, u64 fd_readwrite_nbytes (filled for fd events), u16 flags, then 6 bytes of padding.

func (*WasiStubs) Proc_exit

func (w *WasiStubs) Proc_exit(m *Module, code int32)

func (*WasiStubs) Proc_exit64 added in v0.5.0

func (w *WasiStubs) Proc_exit64(m *Module, code int64)

func (*WasiStubs) Proc_raise

func (w *WasiStubs) Proc_raise(m *Module, sig int32) int32

func (*WasiStubs) Proc_spawn added in v0.3.0

func (w *WasiStubs) Proc_spawn(m *Module, pathPtr, argvPtr, envpPtr, stdinFd, stdoutFd, stderrFd, pidOutPtr int32) int32

Proc_spawn is a NON-STANDARD host import (module wasi_snapshot_preview1, name "proc_spawn") backing the bridge's posix_spawn(). It spawns a HOST process: path is the executable, argv/envp are NUL-terminated char** in linear memory. The child inherits the interpreter's stdin/stdout/stderr. The new pid token is written at pidOutPtr. Returns 0 or a negative errno.

Only stdio inheritance is supported today (no fd remapping / pipes), which covers subprocess.run/call with default streams; capture_output via host pipes is a follow-up.

func (*WasiStubs) Proc_wait added in v0.3.0

func (w *WasiStubs) Proc_wait(m *Module, pid, options, statusOutPtr int32) int32

Proc_wait is a NON-STANDARD host import (name "proc_wait") backing the bridge's waitpid(). It waits for the process token pid and writes the POSIX wait status at statusOutPtr. options is the waitpid() options mask; bit 0 (WNOHANG) makes it return without blocking when the child is still running (the guest sees the documented "0 means no child ready" result, signalled by writing pid 0 — encoded by returning EAGAIN). Returns 0, or a negative errno (ECHILD for an unknown pid).

func (*WasiStubs) Random_get

func (w *WasiStubs) Random_get(m *Module, buf, bufLen int32) int32

func (*WasiStubs) Random_get64 added in v0.5.0

func (w *WasiStubs) Random_get64(m *Module, buf, bufLen int64) int32

func (*WasiStubs) Sched_yield

func (w *WasiStubs) Sched_yield(m *Module) int32

func (*WasiStubs) Sched_yield64 added in v0.5.3

func (w *WasiStubs) Sched_yield64(m *Module) int32

func (*WasiStubs) SetArgs added in v0.3.0

func (w *WasiStubs) SetArgs(args []string)

SetArgs overrides os.Args as seen by the guest (argv). Mirrors SetEnv.

func (*WasiStubs) SetDialHook added in v0.3.0

func (w *WasiStubs) SetDialHook(hook func(network, host, ip string, port int) bool)

SetDialHook installs a host-controlled OUTBOUND-connection policy. hook is called with ("tcp", host, dotted-quad-IP, port) before each Sock_connect, where host is the name the guest resolved to reach the IP (from the preceding Sock_getaddrinfo) or "" for a literal-IP dial; returning false denies the connection (the guest sees a connect EACCES). Pass nil to clear (all outbound allowed, the default once outbound is wired).

func (*WasiStubs) SetEnv added in v0.3.0

func (w *WasiStubs) SetEnv(env []string)

SetEnv overrides the environment the guest sees via environ_get / environ_sizes_get. By default DefaultWASI leaks the host process os.Environ(); a sandboxed embedding should call SetEnv with an explicit (possibly empty) slice of "KEY=VALUE" strings.

func (*WasiStubs) SetExecHook added in v0.3.0

func (w *WasiStubs) SetExecHook(hook func(path string, argv []string) bool)

SetExecHook installs the process-spawn whitelist consulted by Proc_spawn with the executable path and full argv. Returning false denies the spawn (the guest's posix_spawn sees EACCES). Spawning runs a HOST binary, so a sandbox enabling host processes should always set this.

func (*WasiStubs) SetFS added in v0.3.0

func (w *WasiStubs) SetFS(fsys FS)

SetFS installs a custom filesystem backend. Every guest path operation (open, stat, mkdir, readdir, read, write, ...) is then routed to fsys, so a caller can give a module a private, arbitrary filesystem — for example an in-memory FS so writes never touch disk and are invisible to other modules. Pass nil to restore the default os-backed filesystem.

func (*WasiStubs) SetFSAccessHook added in v0.3.0

func (w *WasiStubs) SetFSAccessHook(hook func(path string, write bool) bool)

SetFSAccessHook installs a host-controlled filesystem access policy. hook is called with the guest path (relative to the preopen) and a write flag before each open/create/unlink; returning false denies the operation (the guest sees EACCES). Pass nil to clear the policy (unrestricted, the default). The hook runs without w.mu held, so it may itself call back into the host freely.

func (*WasiStubs) SetNetAccessHook added in v0.3.0

func (w *WasiStubs) SetNetAccessHook(hook func(op string) bool)

SetNetAccessHook installs a host-controlled network access policy. hook is called with the operation name ("accept"/"recv"/"send") before each socket operation; returning false denies it (EACCES). Pass nil to clear (unrestricted, the default).

NOTE: WASI preview1 has no outbound connect or name resolution, so a guest cannot initiate connections regardless of this hook; it governs the accept/recv/send surface that preview1 does expose (host-preopened listening sockets). Full outbound control requires a host connect import, which this runtime does not yet provide.

func (*WasiStubs) SetPreopenDir

func (w *WasiStubs) SetPreopenDir(dir string)

SetPreopenDir scopes the default (os-backed) filesystem to a host directory. Empty string restores the default ("/"), i.e. no rewriting. Tests use this to run filesystem syscalls against t.TempDir(). Has no effect once SetFS has installed a non-os backend.

func (*WasiStubs) SetResolveHook added in v0.3.0

func (w *WasiStubs) SetResolveHook(hook func(host string) bool)

SetResolveHook installs a host-controlled name-resolution policy. hook is called with the host being resolved (Sock_getaddrinfo) before the lookup; returning false denies it (the guest sees a name-resolution error). Pass nil to clear (all lookups allowed). This is where a hostname whitelist such as "block example.com" is enforced.

func (*WasiStubs) SetStderr added in v0.3.0

func (w *WasiStubs) SetStderr(wr io.Writer)

SetStderr redirects guest fd 2 to wr. A nil wr leaves the current sink.

func (*WasiStubs) SetStdin added in v0.3.0

func (w *WasiStubs) SetStdin(r io.Reader)

SetStdin redirects guest fd 0 to r. A nil r leaves the current source. Use this to feed input() / sys.stdin from an in-process io.Reader instead of the host process stdin.

func (*WasiStubs) SetStdout added in v0.3.0

func (w *WasiStubs) SetStdout(wr io.Writer)

SetStdout redirects guest fd 1 to wr. A nil wr leaves the current sink.

func (*WasiStubs) Sock_accept

func (w *WasiStubs) Sock_accept(m *Module, fd, flags, fdOutPtr int32) int32

Sock_accept accepts the next incoming TCP/Unix connection on the listener associated with fd, registers it as a new wasiOpen with a conn arm, and writes the new fd at fdOutPtr. Returns ENOTSOCK if fd isn't a listener.

func (*WasiStubs) Sock_connect added in v0.3.0

func (w *WasiStubs) Sock_connect(m *Module, fd, ipBE, port int32) int32

Sock_connect is a NON-STANDARD host import (module wasi_snapshot_preview1, name "sock_connect") backing a libc connect() wrapped via -Wl,--wrap=connect. ipBE carries the IPv4 address in network byte order exactly as it sat in sockaddr_in.sin_addr.s_addr (so the low byte is the first octet); port is host byte order. It consults the dial whitelist, dials via Go's net, and attaches the resulting conn to the socket fd so the existing Sock_send / Sock_recv / Fd_close paths drive it. Returns 0 or a negative errno.

func (*WasiStubs) Sock_getaddrinfo added in v0.3.0

func (w *WasiStubs) Sock_getaddrinfo(m *Module, nodePtr, nodeLen, outPtr int32) int32

Sock_getaddrinfo is a NON-STANDARD host import (module wasi_snapshot_preview1, name "sock_getaddrinfo") backing the bridge's getaddrinfo(). It reads the host string at (nodePtr,nodeLen), consults the resolve whitelist, resolves it to an IPv4 address via Go's resolver (numeric IPs pass through), and writes the 4-byte network-order address at outPtr. Returns 0 on success or a negative POSIX-ish errno (the bridge maps it to an EAI_* code).

func (*WasiStubs) Sock_recv

func (w *WasiStubs) Sock_recv(m *Module, fd, riData, riDataLen, riFlags, roDataLenPtr, roFlagsPtr int32) int32

func (*WasiStubs) Sock_send

func (w *WasiStubs) Sock_send(m *Module, fd, siData, siDataLen, siFlags, soDataLenPtr int32) int32

func (*WasiStubs) Sock_shutdown

func (w *WasiStubs) Sock_shutdown(m *Module, fd, how int32) int32

func (*WasiStubs) Sock_socket added in v0.3.0

func (w *WasiStubs) Sock_socket(m *Module, domain, typ int32) int32

Sock_socket is a NON-STANDARD host import (module wasi_snapshot_preview1, name "sock_socket") that backs a libc socket() call wrapped via -Wl,--wrap=socket in the guest. WASI preview1 has no way to create an outbound socket; this gives the guest a host-managed fd whose connection is established later by Sock_connect. domain/type follow the POSIX socket() args (AF_INET / SOCK_STREAM); only TCP over IPv4 is supported. Returns the new fd, or a negative errno on failure.

Directories

Path Synopsis
Package helpers contains the runtime helper functions injected into wasm2go's generated output.
Package helpers contains the runtime helper functions injected into wasm2go's generated output.
Package sharedimage carries the copy-on-write shared-memory-image runtime that wasm2go emits alongside a translated module.
Package sharedimage carries the copy-on-write shared-memory-image runtime that wasm2go emits alongside a translated module.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL