@@ -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"
@@ -416,14 +417,14 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
416417 c .addError (f .Signature .Results ().At (1 ).Pos (), fmt .Sprintf ("%s: too many return values" , pragma ))
417418 } else if f .Signature .Results ().Len () == 1 {
418419 result := f .Signature .Results ().At (0 )
419- if ! isValidWasmType (result .Type (), siteResult ) {
420+ if ! c . isValidWasmType (result .Type (), siteResult ) {
420421 c .addError (result .Pos (), fmt .Sprintf ("%s: unsupported result type %s" , pragma , result .Type ().String ()))
421422 }
422423 }
423424 for _ , param := range f .Params {
424425 // Check whether the type is allowed.
425426 // Only a very limited number of types can be mapped to WebAssembly.
426- if ! isValidWasmType (param .Type (), siteParam ) {
427+ if ! c . isValidWasmType (param .Type (), siteParam ) {
427428 c .addError (param .Pos (), fmt .Sprintf ("%s: unsupported parameter type %s" , pragma , param .Type ().String ()))
428429 }
429430 }
@@ -436,7 +437,7 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
436437//
437438// This previously reflected the additional restrictions documented here:
438439// https://github.com/golang/go/issues/59149
439- func isValidWasmType (typ types.Type , site wasmSite ) bool {
440+ func ( c * compilerContext ) isValidWasmType (typ types.Type , site wasmSite ) bool {
440441 switch typ := typ .Underlying ().(type ) {
441442 case * types.Basic :
442443 switch typ .Kind () {
@@ -455,19 +456,32 @@ func isValidWasmType(typ types.Type, site wasmSite) bool {
455456 return site == siteParam || site == siteIndirect
456457 }
457458 case * types.Array :
458- return site == siteIndirect && isValidWasmType (typ .Elem (), siteIndirect )
459+ return site == siteIndirect && c . isValidWasmType (typ .Elem (), siteIndirect )
459460 case * types.Struct :
460461 if site != siteIndirect {
461462 return false
462463 }
464+ // Structs with no fields do not need structs.HostLayout
465+ if typ .NumFields () == 0 {
466+ return true
467+ }
468+ var hasHostLayout bool
469+ if ! goenv .WantGoVersion (c .pkg .GoVersion (), 1 , 23 ) {
470+ hasHostLayout = true // package structs does not exist before go1.23
471+ }
463472 for i := 0 ; i < typ .NumFields (); i ++ {
464- if ! isValidWasmType (typ .Field (i ).Type (), siteIndirect ) {
473+ ftyp := typ .Field (i ).Type ()
474+ if ftyp .String () == "structs.HostLayout" {
475+ hasHostLayout = true
476+ continue
477+ }
478+ if ! c .isValidWasmType (ftyp , siteIndirect ) {
465479 return false
466480 }
467481 }
468- return true
482+ return hasHostLayout
469483 case * types.Pointer :
470- return isValidWasmType (typ .Elem (), siteIndirect )
484+ return c . isValidWasmType (typ .Elem (), siteIndirect )
471485 }
472486 return false
473487}
0 commit comments