Skip to content

Commit 40a60b0

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 c702be7 commit 40a60b0

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"
@@ -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

Comments
 (0)