aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2024-07-02 07:02:03 -0700
committerGitHub <[email protected]>2024-07-02 07:02:03 -0700
commit9cb263479c4b98f2d28889ca1acc297454e0d875 (patch)
treea30bcf8ef9086c5b8edfcee3b42bef352f396878 /compiler
parentf18c6e342f834988caf43fd652b2baae9c3093f0 (diff)
downloadtinygo-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.go48
-rw-r--r--compiler/testdata/errors.go60
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