diff options
author | Damian Gryski <[email protected]> | 2024-07-02 07:02:03 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2024-07-02 07:02:03 -0700 |
commit | 9cb263479c4b98f2d28889ca1acc297454e0d875 (patch) | |
tree | a30bcf8ef9086c5b8edfcee3b42bef352f396878 /compiler | |
parent | f18c6e342f834988caf43fd652b2baae9c3093f0 (diff) | |
download | tinygo-9cb263479c4b98f2d28889ca1acc297454e0d875.tar.gz tinygo-9cb263479c4b98f2d28889ca1acc297454e0d875.zip |
wasi preview 2 support (#4027)
* all: wasip2 support
Co-authored-by: Randy Reddig <[email protected]>
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/symbol.go | 48 | ||||
-rw-r--r-- | compiler/testdata/errors.go | 60 |
2 files changed, 86 insertions, 22 deletions
diff --git a/compiler/symbol.go b/compiler/symbol.go index bf5ac5f1b..5ebdee147 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -346,7 +346,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) { // The list of allowed types is based on this proposal: // https://github.com/golang/go/issues/59149 func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) { - if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" { + if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" { // The runtime is a special case. Allow all kinds of parameters // (importantly, including pointers). return @@ -360,38 +360,68 @@ func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) { c.addError(f.Signature.Results().At(1).Pos(), fmt.Sprintf("%s: too many return values", pragma)) } else if f.Signature.Results().Len() == 1 { result := f.Signature.Results().At(0) - if !isValidWasmType(result.Type(), true) { + if !isValidWasmType(result.Type(), siteResult) { c.addError(result.Pos(), fmt.Sprintf("%s: unsupported result type %s", pragma, result.Type().String())) } } for _, param := range f.Params { // Check whether the type is allowed. // Only a very limited number of types can be mapped to WebAssembly. - if !isValidWasmType(param.Type(), false) { + if !isValidWasmType(param.Type(), siteParam) { c.addError(param.Pos(), fmt.Sprintf("%s: unsupported parameter type %s", pragma, param.Type().String())) } } } -// Check whether the type maps directly to a WebAssembly type, according to: +// Check whether the type maps directly to a WebAssembly type. +// +// This reflects the relaxed type restrictions proposed here (except for structs.HostLayout): +// https://github.com/golang/go/issues/66984 +// +// This previously reflected the additional restrictions documented here: // https://github.com/golang/go/issues/59149 -func isValidWasmType(typ types.Type, isReturn bool) bool { +func isValidWasmType(typ types.Type, site wasmSite) bool { switch typ := typ.Underlying().(type) { case *types.Basic: switch typ.Kind() { - case types.Int32, types.Uint32, types.Int64, types.Uint64: + case types.Bool: + return true + case types.Int, types.Uint, types.Int8, types.Uint8, types.Int16, types.Uint16, types.Int32, types.Uint32, types.Int64, types.Uint64: return true case types.Float32, types.Float64: return true - case types.UnsafePointer: - if !isReturn { - return true + case types.Uintptr, types.UnsafePointer: + return true + case types.String: + // string flattens to two values, so disallowed as a result + return site == siteParam || site == siteIndirect + } + case *types.Array: + return site == siteIndirect && isValidWasmType(typ.Elem(), siteIndirect) + case *types.Struct: + if site != siteIndirect { + return false + } + for i := 0; i < typ.NumFields(); i++ { + if !isValidWasmType(typ.Field(i).Type(), siteIndirect) { + return false } } + return true + case *types.Pointer: + return isValidWasmType(typ.Elem(), siteIndirect) } return false } +type wasmSite int + +const ( + siteParam wasmSite = iota + siteResult + siteIndirect // pointer or field +) + // getParams returns the function parameters, including the receiver at the // start. This is an alternative to the Params member of *ssa.Function, which is // not yet populated when the package has not yet been built. diff --git a/compiler/testdata/errors.go b/compiler/testdata/errors.go index 5778a931e..81e8a76a1 100644 --- a/compiler/testdata/errors.go +++ b/compiler/testdata/errors.go @@ -13,31 +13,65 @@ func implementation() { type Uint uint32 +type S struct { + a [4]uint32 + b uintptr + c int + d float32 + e float64 +} + //go:wasmimport modulename validparam -func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint) +func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint, f uintptr, g string, h *int32, i *S) -// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int -// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type string +// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type [4]uint32 // ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte -// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type *int32 +// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type struct{a int} +// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type chan struct{} +// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type func() // //go:wasmimport modulename invalidparam -func invalidparam(a int, b string, c []byte, d *int32) +func invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func()) + +//go:wasmimport modulename validreturn_int32 +func validreturn_int32() int32 + +//go:wasmimport modulename validreturn_int +func validreturn_int() int + +//go:wasmimport modulename validreturn_ptr_int32 +func validreturn_ptr_int32() *int32 + +//go:wasmimport modulename validreturn_ptr_string +func validreturn_ptr_string() *string -//go:wasmimport modulename validreturn -func validreturn() int32 +//go:wasmimport modulename validreturn_ptr_struct +func validreturn_ptr_struct() *S + +//go:wasmimport modulename validreturn_unsafe_pointer +func validreturn_unsafe_pointer() unsafe.Pointer // ERROR: //go:wasmimport modulename manyreturns: too many return values // //go:wasmimport modulename manyreturns func manyreturns() (int32, int32) -// ERROR: //go:wasmimport modulename invalidreturn: unsupported result type int +// ERROR: //go:wasmimport modulename invalidreturn_func: unsupported result type func() +// +//go:wasmimport modulename invalidreturn_func +func invalidreturn_func() func() + +// ERROR: //go:wasmimport modulename invalidreturn_slice_byte: unsupported result type []byte +// +//go:wasmimport modulename invalidreturn_slice_byte +func invalidreturn_slice_byte() []byte + +// ERROR: //go:wasmimport modulename invalidreturn_chan_int: unsupported result type chan int // -//go:wasmimport modulename invalidreturn -func invalidreturn() int +//go:wasmimport modulename invalidreturn_chan_int +func invalidreturn_chan_int() chan int -// ERROR: //go:wasmimport modulename invalidUnsafePointerReturn: unsupported result type unsafe.Pointer +// ERROR: //go:wasmimport modulename invalidreturn_string: unsupported result type string // -//go:wasmimport modulename invalidUnsafePointerReturn -func invalidUnsafePointerReturn() unsafe.Pointer +//go:wasmimport modulename invalidreturn_string +func invalidreturn_string() string |