Skip to content

Commit

Permalink
Merge pull request #177 from bytecodealliance/ydnar/hostlayout
Browse files Browse the repository at this point in the history
cm, wit/bindgen: add HostLayout field to generated structs
  • Loading branch information
ydnar authored Sep 24, 2024
2 parents 2623075 + 45615b2 commit b0ee41a
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 15 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### Added

- Generated structs and structs in package `cm` now include a [`HostLayout` field](https://github.com/golang/go/issues/66408) in order to conform with the [relaxed types proposal](https://github.com/golang/go/issues/66984) for `GOARCH=wasm32`. The `cm.HostLayout` type is an alias for `structs.HostLayout` on Go 1.23 or later, and a polyfill for Go 1.22 or earlier.
- [#163](https://github.com/bytecodealliance/wasm-tools-go/issues/163): added `cm.F32ToU64()` and `cm.U64ToF32()` for flattening `f32` and `u64` types in the Canonical ABI.
- Test data from [bytecodealliance/wit-bindgen/tests/codegen](https://github.com/bytecodealliance/wit-bindgen/tree/main/tests/codegen)
- Test data from [bytecodealliance/wit-bindgen/tests/codegen](https://github.com/bytecodealliance/wit-bindgen/tree/main/tests/codegen).

### Fixed

Expand Down
11 changes: 11 additions & 0 deletions cm/hostlayout_go122.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build !go1.23

package cm

// HostLayout marks a struct as using host memory layout.
// See [structs.HostLayout] in Go 1.23 or later.
type HostLayout struct {
_ hostLayout // prevent accidental conversion with plain struct{}
}

type hostLayout struct{}
9 changes: 9 additions & 0 deletions cm/hostlayout_go123.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build go1.23

package cm

import "structs"

// HostLayout marks a struct as using host memory layout.
// See [structs.HostLayout] in Go 1.23 or later.
type HostLayout = structs.HostLayout
4 changes: 4 additions & 0 deletions cm/layout_test.go → cm/hostlayout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

func TestFieldAlignment(t *testing.T) {
var v1 struct {
_ HostLayout
_ bool
_ [0][7]byte
u64 uint64
Expand All @@ -22,6 +23,7 @@ func TestFieldAlignment(t *testing.T) {
}

var v2 struct {
_ HostLayout
_ bool
_ [0][7]byte
_ [0][51]float64
Expand All @@ -40,6 +42,7 @@ func TestFieldAlignment(t *testing.T) {

// size 1
var v3 struct {
_ HostLayout
_ struct{}
b bool // offset 0
}
Expand All @@ -52,6 +55,7 @@ func TestFieldAlignment(t *testing.T) {

// size 0
var v4 struct {
_ HostLayout
_ [0]uint32
b bool // offset 0!
}
Expand Down
1 change: 1 addition & 0 deletions cm/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func ToList[S ~[]T, T any](s S) List[T] {
// It is intended to be embedded in a [List], so embedding types maintain
// the methods defined on this type.
type list[T any] struct {
_ HostLayout
data *T
len uint
}
Expand Down
1 change: 1 addition & 0 deletions cm/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func Some[T any](v T) Option[T] {
// The first byte is a bool representing none or some,
// followed by storage for the associated type T.
type option[T any] struct {
_ HostLayout
isSome bool
some T
}
Expand Down
1 change: 1 addition & 0 deletions cm/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Result[Shape, OK, Err any] struct{ result[Shape, OK, Err] }

// result represents the internal representation of a Component Model result type.
type result[Shape, OK, Err any] struct {
_ HostLayout
isErr bool
_ [0]OK
_ [0]Err
Expand Down
1 change: 1 addition & 0 deletions cm/result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ func TestIssue95Struct(t *testing.T) {
type (
// structResult Result[structVariant, stringStruct, structVariant]
stringStruct struct {
_ HostLayout
// i int
s string
}
Expand Down
15 changes: 15 additions & 0 deletions cm/tuple.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package cm
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple[T0, T1 any] struct {
_ HostLayout
F0 T0
F1 T1
}
Expand All @@ -12,6 +13,7 @@ type Tuple[T0, T1 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple3[T0, T1, T2 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -21,6 +23,7 @@ type Tuple3[T0, T1, T2 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple4[T0, T1, T2, T3 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -31,6 +34,7 @@ type Tuple4[T0, T1, T2, T3 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple5[T0, T1, T2, T3, T4 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -42,6 +46,7 @@ type Tuple5[T0, T1, T2, T3, T4 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple6[T0, T1, T2, T3, T4, T5 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -54,6 +59,7 @@ type Tuple6[T0, T1, T2, T3, T4, T5 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple7[T0, T1, T2, T3, T4, T5, T6 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -67,6 +73,7 @@ type Tuple7[T0, T1, T2, T3, T4, T5, T6 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -81,6 +88,7 @@ type Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -96,6 +104,7 @@ type Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -112,6 +121,7 @@ type Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -129,6 +139,7 @@ type Tuple11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -147,6 +158,7 @@ type Tuple12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -166,6 +178,7 @@ type Tuple13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -186,6 +199,7 @@ type Tuple14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] str
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand All @@ -207,6 +221,7 @@ type Tuple15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any
//
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
type Tuple16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any] struct {
_ HostLayout
F0 T0
F1 T1
F2 T2
Expand Down
15 changes: 8 additions & 7 deletions cm/tuple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
)

func TestTuple(t *testing.T) {
_ = Tuple[string, bool]{"hello", false}
_ = Tuple3[string, bool, uint8]{"hello", false, 1}
_ = Tuple4[string, bool, uint8, uint16]{"hello", false, 1, 32000}
_ = Tuple5[string, bool, uint8, uint16, uint32]{"hello", false, 1, 32000, 1_000_000}
_ = Tuple6[string, bool, uint8, uint16, uint32, uint64]{"hello", false, 1, 32000, 1_000_000, 5_000_000_000}
_ = Tuple7[string, bool, uint8, uint16, uint32, uint64, float32]{"hello", false, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64, math.MaxFloat32}
_ = Tuple8[string, bool, uint8, uint16, uint32, uint64, float32, float64]{"hello", false, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64, math.MaxFloat32, math.MaxFloat64}
var HL HostLayout
_ = Tuple[string, bool]{HL, "hello", false}
_ = Tuple3[string, bool, uint8]{HL, "hello", false, 1}
_ = Tuple4[string, bool, uint8, uint16]{HL, "hello", false, 1, 32000}
_ = Tuple5[string, bool, uint8, uint16, uint32]{HL, "hello", false, 1, 32000, 1_000_000}
_ = Tuple6[string, bool, uint8, uint16, uint32, uint64]{HL, "hello", false, 1, 32000, 1_000_000, 5_000_000_000}
_ = Tuple7[string, bool, uint8, uint16, uint32, uint64, float32]{HL, "hello", false, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64, math.MaxFloat32}
_ = Tuple8[string, bool, uint8, uint16, uint32, uint64, float32, float64]{HL, "hello", false, math.MaxUint8, math.MaxUint16, math.MaxUint32, math.MaxUint64, math.MaxFloat32, math.MaxFloat64}
}
1 change: 1 addition & 0 deletions cm/variant.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func Case[T any, V ~struct{ variant[Tag, Shape, Align] }, Tag Discriminant, Shap
// variant is the internal representation of a Component Model variant.
// Shape and Align must be non-zero sized types.
type variant[Tag Discriminant, Shape, Align any] struct {
_ HostLayout
tag Tag
_ [0]Align
data Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte
Expand Down
2 changes: 2 additions & 0 deletions testdata/example/non-flat-params.wit
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ interface corner-case {
u17-void: func(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8, i: u8, j: u8, k: u8, l: u8, m: u8, n: u8, o: u8, p: u8, q: u8);
u17-u8-u8: func(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8, i: u8, j: u8, k: u8, l: u8, m: u8, n: u8, o: u8, p: u8, q: u8) -> (r0: u8, r1: u8);
}

reserved-names: func(%bool: u8, int8: u8, uint8: u8, int16: u8, uint16: u8, int32: u8, uint32: u8, %f32: u8, %f64: u8, %string: u8, %record: u8, struct: u8, %world: u8, %interface: u8, %option: u8, %package: u8, %result: u8) -> (r0: u8, r1: u8);
}

world imports {
Expand Down
84 changes: 84 additions & 0 deletions testdata/example/non-flat-params.wit.json
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,90 @@
"type": "u8"
}
]
},
"reserved-names": {
"name": "reserved-names",
"kind": "freestanding",
"params": [
{
"name": "bool",
"type": "u8"
},
{
"name": "int8",
"type": "u8"
},
{
"name": "uint8",
"type": "u8"
},
{
"name": "int16",
"type": "u8"
},
{
"name": "uint16",
"type": "u8"
},
{
"name": "int32",
"type": "u8"
},
{
"name": "uint32",
"type": "u8"
},
{
"name": "f32",
"type": "u8"
},
{
"name": "f64",
"type": "u8"
},
{
"name": "string",
"type": "u8"
},
{
"name": "record",
"type": "u8"
},
{
"name": "struct",
"type": "u8"
},
{
"name": "world",
"type": "u8"
},
{
"name": "interface",
"type": "u8"
},
{
"name": "option",
"type": "u8"
},
{
"name": "package",
"type": "u8"
},
{
"name": "result",
"type": "u8"
}
],
"results": [
{
"name": "r0",
"type": "u8"
},
{
"name": "r1",
"type": "u8"
}
]
}
},
"package": 0
Expand Down
1 change: 1 addition & 0 deletions testdata/example/non-flat-params.wit.json.golden.wit
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface corner-case {
u16-x17-u8: func(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8, i: u8, j: u8, k: u8, l: u8, m: u8, n: u8, o: u8, p: u8) -> (a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8, i: u8, j: u8, k: u8, l: u8, m: u8, n: u8, o: u8, p: u8, q: u8);
u17-void: func(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8, i: u8, j: u8, k: u8, l: u8, m: u8, n: u8, o: u8, p: u8, q: u8);
u17-u8-u8: func(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8, i: u8, j: u8, k: u8, l: u8, m: u8, n: u8, o: u8, p: u8, q: u8) -> (r0: u8, r1: u8);
reserved-names: func(%bool: u8, int8: u8, uint8: u8, int16: u8, uint16: u8, int32: u8, uint32: u8, %f32: u8, %f64: u8, %string: u8, %record: u8, struct: u8, %world: u8, %interface: u8, %option: u8, %package: u8, %result: u8) -> (r0: u8, r1: u8);
}

world imports {
Expand Down
7 changes: 5 additions & 2 deletions wit/bindgen/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,9 @@ func (g *generator) primitiveRep(p wit.Primitive) string {
func (g *generator) recordRep(file *gen.File, dir wit.Direction, r *wit.Record, goName string) string {
exported := len(goName) == 0 || token.IsExported(goName)
var b strings.Builder
b.WriteString("struct {")
cm := file.Import(g.opts.cmPackage)
b.WriteString("struct {\n")
stringio.Write(&b, "_ ", cm, ".HostLayout")
for i, f := range r.Fields {
if i == 0 || i > 0 && f.Docs.Contents != "" {
b.WriteRune('\n')
Expand Down Expand Up @@ -1728,7 +1730,8 @@ func (g *generator) defineImportedFunction(_ wit.Ident, f *wit.Function, decl fu
if i > 0 {
b.WriteString(", ")
}
b.WriteString(p.name)
// compound parameter struct field names are identical to parameter names
stringio.Write(&b, p.name, ": ", p.name)
}
b.WriteString(" }\n")
} else if len(callParams) > 0 {
Expand Down
Loading

0 comments on commit b0ee41a

Please sign in to comment.