Skip to content

Commit 77bde39

Browse files
committed
compiler: enforce structs.HostLayout usage per wasm types proposal
golang/go#66984 TODO: regenerate WASI syscall packages for GC shape types including structs.HostLayout compiler: require go1.23 for structs.HostLayout
1 parent c3ad182 commit 77bde39

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

compiler/symbol.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)