Skip to content

Commit a5669c9

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 compiler: use an interface to check if GoVersion() exists This permits TinyGo to compile with Go 1.21. compiler: use goenv.Compare instead of WantGoVersion
1 parent cd7ddba commit a5669c9

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

compiler/symbol.go

Lines changed: 24 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,35 @@ 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+
hasHostLayout := true // default to true before detecting Go version
475+
// (*types.Package).GoVersion added in go1.21
476+
if gv, ok := any(c.pkg).(interface{ GoVersion() string }); ok {
477+
if goenv.Compare(gv.GoVersion(), "go1.23") >= 0 {
478+
hasHostLayout = false // package structs added in go1.23
479+
}
480+
}
469481
for i := 0; i < typ.NumFields(); i++ {
470-
if !isValidWasmType(typ.Field(i).Type(), siteIndirect) {
482+
ftyp := typ.Field(i).Type()
483+
if ftyp.String() == "structs.HostLayout" {
484+
hasHostLayout = true
485+
continue
486+
}
487+
if !c.isValidWasmType(ftyp, siteIndirect) {
471488
return false
472489
}
473490
}
474-
return true
491+
return hasHostLayout
475492
case *types.Pointer:
476-
return isValidWasmType(typ.Elem(), siteIndirect)
493+
return c.isValidWasmType(typ.Elem(), siteIndirect)
477494
}
478495
return false
479496
}

0 commit comments

Comments
 (0)