@@ -416,14 +416,14 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
416416 c .addError (f .Signature .Results ().At (1 ).Pos (), fmt .Sprintf ("%s: too many return values" , pragma ))
417417 } else if f .Signature .Results ().Len () == 1 {
418418 result := f .Signature .Results ().At (0 )
419- if ! isValidWasmType (result .Type (), siteResult ) {
419+ if ! c . isValidWasmType (result .Type (), siteResult ) {
420420 c .addError (result .Pos (), fmt .Sprintf ("%s: unsupported result type %s" , pragma , result .Type ().String ()))
421421 }
422422 }
423423 for _ , param := range f .Params {
424424 // Check whether the type is allowed.
425425 // Only a very limited number of types can be mapped to WebAssembly.
426- if ! isValidWasmType (param .Type (), siteParam ) {
426+ if ! c . isValidWasmType (param .Type (), siteParam ) {
427427 c .addError (param .Pos (), fmt .Sprintf ("%s: unsupported parameter type %s" , pragma , param .Type ().String ()))
428428 }
429429 }
@@ -436,7 +436,7 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
436436//
437437// This previously reflected the additional restrictions documented here:
438438// https://github.com/golang/go/issues/59149
439- func isValidWasmType (typ types.Type , site wasmSite ) bool {
439+ func ( c * compilerContext ) isValidWasmType (typ types.Type , site wasmSite ) bool {
440440 switch typ := typ .Underlying ().(type ) {
441441 case * types.Basic :
442442 switch typ .Kind () {
@@ -455,19 +455,32 @@ func isValidWasmType(typ types.Type, site wasmSite) bool {
455455 return site == siteParam || site == siteIndirect
456456 }
457457 case * types.Array :
458- return site == siteIndirect && isValidWasmType (typ .Elem (), siteIndirect )
458+ return site == siteIndirect && c . isValidWasmType (typ .Elem (), siteIndirect )
459459 case * types.Struct :
460460 if site != siteIndirect {
461461 return false
462462 }
463+ // Structs with no fields do not need structs.HostLayout
464+ if typ .NumFields () == 0 {
465+ return true
466+ }
467+ var hasHostLayout bool
468+ if c .program .ImportedPackage ("structs" ) == nil {
469+ hasHostLayout = true // package structs does not exist before go1.23
470+ }
463471 for i := 0 ; i < typ .NumFields (); i ++ {
464- if ! isValidWasmType (typ .Field (i ).Type (), siteIndirect ) {
472+ ftyp := typ .Field (i ).Type ()
473+ if ftyp .String () == "structs.HostLayout" {
474+ hasHostLayout = true
475+ continue
476+ }
477+ if ! c .isValidWasmType (ftyp , siteIndirect ) {
465478 return false
466479 }
467480 }
468- return true
481+ return hasHostLayout
469482 case * types.Pointer :
470- return isValidWasmType (typ .Elem (), siteIndirect )
483+ return c . isValidWasmType (typ .Elem (), siteIndirect )
471484 }
472485 return false
473486}
0 commit comments