@@ -12,6 +12,7 @@ import (
1212 "strings"
1313
1414 "github.com/tinygo-org/tinygo/compiler/llvmutil"
15+ "github.com/tinygo-org/tinygo/goenv"
1516 "github.com/tinygo-org/tinygo/loader"
1617 "golang.org/x/tools/go/ssa"
1718 "tinygo.org/x/go-llvm"
@@ -422,14 +423,14 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
422423 c .addError (f .Signature .Results ().At (1 ).Pos (), fmt .Sprintf ("%s: too many return values" , pragma ))
423424 } else if f .Signature .Results ().Len () == 1 {
424425 result := f .Signature .Results ().At (0 )
425- if ! isValidWasmType (result .Type (), siteResult ) {
426+ if ! c . isValidWasmType (result .Type (), siteResult ) {
426427 c .addError (result .Pos (), fmt .Sprintf ("%s: unsupported result type %s" , pragma , result .Type ().String ()))
427428 }
428429 }
429430 for _ , param := range f .Params {
430431 // Check whether the type is allowed.
431432 // Only a very limited number of types can be mapped to WebAssembly.
432- if ! isValidWasmType (param .Type (), siteParam ) {
433+ if ! c . isValidWasmType (param .Type (), siteParam ) {
433434 c .addError (param .Pos (), fmt .Sprintf ("%s: unsupported parameter type %s" , pragma , param .Type ().String ()))
434435 }
435436 }
@@ -442,7 +443,7 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
442443//
443444// This previously reflected the additional restrictions documented here:
444445// https://github.com/golang/go/issues/59149
445- func isValidWasmType (typ types.Type , site wasmSite ) bool {
446+ func ( c * compilerContext ) isValidWasmType (typ types.Type , site wasmSite ) bool {
446447 switch typ := typ .Underlying ().(type ) {
447448 case * types.Basic :
448449 switch typ .Kind () {
@@ -461,19 +462,32 @@ func isValidWasmType(typ types.Type, site wasmSite) bool {
461462 return site == siteParam || site == siteIndirect
462463 }
463464 case * types.Array :
464- return site == siteIndirect && isValidWasmType (typ .Elem (), siteIndirect )
465+ return site == siteIndirect && c . isValidWasmType (typ .Elem (), siteIndirect )
465466 case * types.Struct :
466467 if site != siteIndirect {
467468 return false
468469 }
470+ // Structs with no fields do not need structs.HostLayout
471+ if typ .NumFields () == 0 {
472+ return true
473+ }
474+ var hasHostLayout bool
475+ if ! goenv .WantGoVersion (c .pkg .GoVersion (), 1 , 23 ) {
476+ hasHostLayout = true // package structs does not exist before go1.23
477+ }
469478 for i := 0 ; i < typ .NumFields (); i ++ {
470- if ! isValidWasmType (typ .Field (i ).Type (), siteIndirect ) {
479+ ftyp := typ .Field (i ).Type ()
480+ if ftyp .String () == "structs.HostLayout" {
481+ hasHostLayout = true
482+ continue
483+ }
484+ if ! c .isValidWasmType (ftyp , siteIndirect ) {
471485 return false
472486 }
473487 }
474- return true
488+ return hasHostLayout
475489 case * types.Pointer :
476- return isValidWasmType (typ .Elem (), siteIndirect )
490+ return c . isValidWasmType (typ .Elem (), siteIndirect )
477491 }
478492 return false
479493}
0 commit comments