Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion internal/wasm-tools/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ module github.com/tinygo-org/tinygo/internal/tools

go 1.22.4

require github.com/bytecodealliance/wasm-tools-go v0.2.0
require github.com/bytecodealliance/wasm-tools-go v0.3.0

require (
github.com/coreos/go-semver v0.3.1 // indirect
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/regclient/regclient v0.7.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/urfave/cli/v3 v3.0.0-alpha9 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sys v0.26.0 // indirect
)
29 changes: 25 additions & 4 deletions internal/wasm-tools/go.sum
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
github.com/bytecodealliance/wasm-tools-go v0.2.0 h1:JdmiZew7ewHjf+ZGGRE4gZM85Ad/PGW/5I57hepEOjQ=
github.com/bytecodealliance/wasm-tools-go v0.2.0/go.mod h1:2GnJCUlcDrslZ/L6+yYqoUnewDlBvqRS2N/0NW9ro6w=
github.com/bytecodealliance/wasm-tools-go v0.3.0 h1:9aeDFYpbi3gtIW/nJCH+P+LhFMqezGoOfzqbUZLadho=
github.com/bytecodealliance/wasm-tools-go v0.3.0/go.mod h1:VY+9FlpLi6jnhCrZLkyJjF9rjU4aEekgaRTk28MS2JE=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/olareg/olareg v0.1.0 h1:1dXBOgPrig5N7zoXyIZVQqU0QBo6sD9pbL6UYjY75CA=
github.com/olareg/olareg v0.1.0/go.mod h1:RBuU7JW7SoIIxZKzLRhq8sVtQeAHzCAtRrXEBx2KlM4=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/regclient/regclient v0.7.1 h1:qEsJrTmZd98fZKjueAbrZCSNGU+ifnr6xjlSAs3WOPs=
github.com/regclient/regclient v0.7.1/go.mod h1:+w/BFtJuw0h0nzIw/z2+1FuA2/dVXBzDq4rYmziJpMc=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v3 v3.0.0-alpha9 h1:P0RMy5fQm1AslQS+XCmy9UknDXctOmG/q/FZkUFnJSo=
github.com/urfave/cli/v3 v3.0.0-alpha9/go.mod h1:0kK/RUFHyh+yIKSfWxwheGndfnrvYSmYFVeKCh03ZUc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
Expand All @@ -18,8 +35,12 @@ golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
32 changes: 28 additions & 4 deletions src/internal/cm/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ package cm

import "unsafe"

// AnyInteger is a type constraint for any integer type.
type AnyInteger interface {
~int | ~uint | ~uintptr | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 | ~int64 | ~uint64
}

// Reinterpret reinterprets the bits of type From into type T.
// Will panic if the size of From is smaller than the size of To.
func Reinterpret[T, From any](from From) (to T) {
Expand All @@ -19,19 +24,19 @@ func LowerString[S ~string](s S) (*byte, uint32) {
}

// LiftString lifts Core WebAssembly types into a [string].
func LiftString[T ~string, Data unsafe.Pointer | uintptr | *uint8, Len uint | uintptr | uint32 | uint64](data Data, len Len) T {
func LiftString[T ~string, Data unsafe.Pointer | uintptr | *uint8, Len AnyInteger](data Data, len Len) T {
return T(unsafe.String((*uint8)(unsafe.Pointer(data)), int(len)))
}

// LowerList lowers a [List] into a pair of Core WebAssembly types.
func LowerList[L ~struct{ list[T] }, T any](list L) (*T, uint32) {
func LowerList[L AnyList[T], T any](list L) (*T, uint32) {
l := (*List[T])(unsafe.Pointer(&list))
return l.data, uint32(l.len)
}

// LiftList lifts Core WebAssembly types into a [List].
func LiftList[L List[T], T any, Data unsafe.Pointer | uintptr | *T, Len uint | uintptr | uint32 | uint64](data Data, len Len) L {
return L(NewList((*T)(unsafe.Pointer(data)), uint(len)))
func LiftList[L AnyList[T], T any, Data unsafe.Pointer | uintptr | *T, Len AnyInteger](data Data, len Len) L {
return L(NewList((*T)(unsafe.Pointer(data)), len))
}

// BoolToU32 converts a value whose underlying type is [bool] into a [uint32].
Expand Down Expand Up @@ -84,6 +89,25 @@ func F64ToU64(v float64) uint64 { return *(*uint64)(unsafe.Pointer(&v)) }
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U64ToF64(v uint64) float64 { return *(*float64)(unsafe.Pointer(&v)) }

// F32ToU64 maps the bits of a [float32] into a [uint64].
// Used to lower a [float32] into a Core WebAssembly i64 when required by the [Canonical ABI].
//
// [float32]: https://pkg.go.dev/builtin#float32
// [uint64]: https://pkg.go.dev/builtin#uint64
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func F32ToU64(v float32) uint64 { return uint64(*(*uint32)(unsafe.Pointer(&v))) }

// U64ToF32 maps the bits of a [uint64] into a [float32].
// Used to lift a Core WebAssembly i64 into a [float32] when required by the [Canonical ABI].
//
// [uint64]: https://pkg.go.dev/builtin#uint64
// [float32]: https://pkg.go.dev/builtin#float32
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U64ToF32(v uint64) float32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should probably apply to the upstream generator, but note that math already has

[func Float32bits(f float32) uint32](https://pkg.go.dev/math#Float32bits)
[func Float32frombits(b uint32) float32](https://pkg.go.dev/math#Float32frombits)
[func Float64bits(f float64) uint64](https://pkg.go.dev/math#Float64bits)
[func Float64frombits(b uint64) float64](https://pkg.go.dev/math#Float64frombits)

Copy link
Contributor Author

@ydnar ydnar Oct 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memorializing IRL conversation this past week in San Francisco:

"We duplicate functionality from package math here to avoid a potential circular dependency in package runtime. Package cm intentionally depends only on unsafe."

truncated := uint32(v)
return *(*float32)(unsafe.Pointer(&truncated))
}

// PointerToU32 converts a pointer of type *T into a [uint32].
// Used to lower a pointer into a Core WebAssembly i32 as specified in the [Canonical ABI].
//
Expand Down
11 changes: 11 additions & 0 deletions src/internal/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 src/internal/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
28 changes: 20 additions & 8 deletions src/internal/cm/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@ import "unsafe"

// List represents a Component Model list.
// The binary representation of list<T> is similar to a Go slice minus the cap field.
type List[T any] struct{ list[T] }
type List[T any] struct {
_ HostLayout
list[T]
}

// AnyList is a type constraint for generic functions that accept any [List] type.
type AnyList[T any] interface {
~struct {
_ HostLayout
list[T]
}
}

// NewList returns a List[T] from data and len.
func NewList[T any](data *T, len uint) List[T] {
func NewList[T any, Len AnyInteger](data *T, len Len) List[T] {
return List[T]{
list[T]{
list: list[T]{
data: data,
len: len,
len: uintptr(len),
},
}
}
Expand All @@ -20,15 +31,16 @@ func NewList[T any](data *T, len uint) List[T] {
// The underlying slice data is not copied, and the resulting List points at the
// same array storage as the slice.
func ToList[S ~[]T, T any](s S) List[T] {
return NewList[T](unsafe.SliceData([]T(s)), uint(len(s)))
return NewList[T](unsafe.SliceData([]T(s)), uintptr(len(s)))
}

// list represents the internal representation of a Component Model list.
// 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
len uintptr
}

// Slice returns a Go slice representing the List.
Expand All @@ -42,7 +54,7 @@ func (l list[T]) Data() *T {
}

// Len returns the length of the list.
// TODO: should this return an int instead of a uint?
func (l list[T]) Len() uint {
// TODO: should this return an int instead of a uintptr?
func (l list[T]) Len() uintptr {
return l.len
}
19 changes: 17 additions & 2 deletions src/internal/cm/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package cm
// Option represents a Component Model [option<T>] type.
//
// [option<T>]: https://component-model.bytecodealliance.org/design/wit.html#options
type Option[T any] struct{ option[T] }
type Option[T any] struct {
_ HostLayout
option[T]
}

// None returns an [Option] representing the none case,
// equivalent to the zero value.
Expand All @@ -14,7 +17,7 @@ func None[T any]() Option[T] {
// Some returns an [Option] representing the some case.
func Some[T any](v T) Option[T] {
return Option[T]{
option[T]{
option: option[T]{
isSome: true,
some: v,
},
Expand All @@ -25,6 +28,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 All @@ -42,3 +46,14 @@ func (o *option[T]) Some() *T {
}
return nil
}

// Value returns T if o represents the some case,
// or the zero value of T if o represents the none case.
// This does not have a pointer receiver, so it can be chained.
func (o option[T]) Value() T {
if !o.isSome {
var zero T
return zero
}
return o.some
}
22 changes: 17 additions & 5 deletions src/internal/cm/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ type BoolResult bool
// Result represents a result sized to hold the Shape type.
// The size of the Shape type must be greater than or equal to the size of OK and Err types.
// For results with two zero-length types, use [BoolResult].
type Result[Shape, OK, Err any] struct{ result[Shape, OK, Err] }
type Result[Shape, OK, Err any] struct {
_ HostLayout
result[Shape, OK, Err]
}

// AnyResult is a type constraint for generic functions that accept any [Result] type.
type AnyResult[Shape, OK, Err any] interface {
~struct {
_ HostLayout
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 Expand Up @@ -88,8 +100,8 @@ func (r *result[Shape, OK, Err]) validate() {

// OK returns an OK result with shape Shape and type OK and Err.
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
func OK[R ~struct{ result[Shape, OK, Err] }, Shape, OK, Err any](ok OK) R {
var r struct{ result[Shape, OK, Err] }
func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
var r Result[Shape, OK, Err]
r.validate()
r.isErr = ResultOK
*((*OK)(unsafe.Pointer(&r.data))) = ok
Expand All @@ -98,8 +110,8 @@ func OK[R ~struct{ result[Shape, OK, Err] }, Shape, OK, Err any](ok OK) R {

// Err returns an error result with shape Shape and type OK and Err.
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
func Err[R ~struct{ result[Shape, OK, Err] }, Shape, OK, Err any](err Err) R {
var r struct{ result[Shape, OK, Err] }
func Err[R AnyResult[Shape, OK, Err], Shape, OK, Err any](err Err) R {
var r Result[Shape, OK, Err]
r.validate()
r.isErr = ResultErr
*((*Err)(unsafe.Pointer(&r.data))) = err
Expand Down
Loading