Skip to content

Commit

Permalink
all: simplify wasm-tools-go dependency
Browse files Browse the repository at this point in the history
- add internal/wasm-tools/go.mod file to depend on wasm-tools-go
- copy package cm into src/internal/cm
- remove wasm-tools-go "vendor" submodule

internal/tools: fix typo

go.{mod,sum}, internal/tools: add wit-bindgen-go to tools

GNUmakefile: use go run for wit-bindgen-go

GNUmakefile: add tools target to go:generate tools binaries in internal/tools

GNUmakefile: add .PHONY for lint and spell

GNUmakefile, internal/cm: vendor package cm into internal/cm

go.{mod,sum}: update wasm-tools-go to v0.1.4

internal/wasi: use internal/cm package

remove submodule src/vendor/github.com/ydnar/wasm-tools-go

GNUmakefile: add comment documenting what wasi-cm target does

go.{mod,sum}: remove toolchain; go mod tidy

go.mod: revert to Go 1.19

go.mod: go 1.19

go.{mod,sum}, internal/{tools,wasm-tools}: revert root go.mod file to go1.19

Create a wasm-tools specific module that can require go1.22 for wasm-tools-go.
  • Loading branch information
ydnar authored and deadprogram committed Jul 17, 2024
1 parent f026422 commit 87a8aaf
Show file tree
Hide file tree
Showing 50 changed files with 760 additions and 46 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,3 @@
[submodule "lib/wasi-cli"]
path = lib/wasi-cli
url = https://github.com/WebAssembly/wasi-cli
[submodule "src/vendor/github.com/ydnar/wasm-tools-go"]
path = src/vendor/github.com/ydnar/wasm-tools-go
url = https://github.com/ydnar/wasm-tools-go.git
19 changes: 16 additions & 3 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,16 @@ lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
cd lib/wasi-libc && $(MAKE) -j4 EXTRA_CFLAGS="-O2 -g -DNDEBUG -mnontrapping-fptoint -msign-ext" MALLOC_IMPL=none CC="$(CLANG)" AR=$(LLVM_AR) NM=$(LLVM_NM)

# Generate WASI syscall bindings
WASM_TOOLS_MODULE=github.com/ydnar/wasm-tools-go
.PHONY: wasi-syscall
wasi-syscall:
wit-bindgen-go generate -o ./src/internal -p internal --versioned ./lib/wasi-cli/wit
wasi-syscall: wasi-cm
go run -modfile ./internal/wasm-tools/go.mod $(WASM_TOOLS_MODULE)/cmd/wit-bindgen-go generate --versioned -o ./src/internal -p internal --cm internal/cm ./lib/wasi-cli/wit

# Copy package cm into src/internal/cm
.PHONY: wasi-cm
wasi-cm:
# rm -rf ./src/internal/cm
rsync -rv --delete --exclude '*_test.go' $(shell go list -modfile ./internal/wasm-tools/go.mod -m -f {{.Dir}} $(WASM_TOOLS_MODULE))/cm ./src/internal/

# Check for Node.js used during WASM tests.
NODEJS_VERSION := $(word 1,$(subst ., ,$(shell node -v | cut -c 2-)))
Expand Down Expand Up @@ -946,6 +953,11 @@ release: build/release
deb: build/release
endif

.PHONY: tools
tools:
go generate -C ./internal/tools -tags tools ./

.PHONY: lint
lint:
go run github.com/mgechev/revive -version
# TODO: lint more directories!
Expand All @@ -954,6 +966,7 @@ lint:
# Use 'grep .' to get rid of stray blank line
go run github.com/mgechev/revive -config revive.toml compiler/... src/{os,reflect}/*.go | grep -v "should have comment or be unexported" | grep '.' | awk '{print}; END {exit NR>0}'

.PHONY: spell
spell:
# Check for typos in comments. Skip git submodules etc.
# Check for typos in comments. Skip git submodules etc.
go run github.com/client9/misspell/cmd/misspell -i 'ackward,devided,extint,inbetween,programmmer,rela' $$( find . -depth 1 -type d | egrep -w -v 'lib|llvm|src/net' )
7 changes: 5 additions & 2 deletions internal/tools/tools.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//go:build tools

// Install linter versions specified in go.mod
// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idom
// Install tools specified in go.mod.
// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idiom.
package tools

import (
_ "github.com/client9/misspell"
_ "github.com/mgechev/revive"
)

//go:generate go install github.com/client9/misspell/cmd/misspell
//go:generate go install github.com/mgechev/revive
5 changes: 5 additions & 0 deletions internal/wasm-tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# wasm-tools directory

This directory has a separate `go.mod` file because the `wasm-tools-go` module requires Go 1.22, while TinyGo itself supports Go 1.19.

When the minimum Go version for TinyGo is 1.22, this directory can be folded into `internal/tools` and the `go.mod` and `go.sum` files deleted.
12 changes: 12 additions & 0 deletions internal/wasm-tools/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/tinygo-org/tinygo/internal/tools

go 1.22.4

require github.com/ydnar/wasm-tools-go v0.1.4

require (
github.com/coreos/go-semver v0.3.1 // 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.19.0 // indirect
)
25 changes: 25 additions & 0 deletions internal/wasm-tools/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
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=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/ydnar/wasm-tools-go v0.1.4 h1:+25WqBj0AhLx8OFvZvrs7bQO6L3WtQ7t6JzQEYsXQb8=
github.com/ydnar/wasm-tools-go v0.1.4/go.mod h1:lQfv2Tde3tRgZDSYriro0EmdSHzP1mrHPMmYNahSS/g=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
11 changes: 11 additions & 0 deletions internal/wasm-tools/tools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build tools

// Install tools specified in go.mod.
// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idiom.
package tools

import (
_ "github.com/ydnar/wasm-tools-go/cmd/wit-bindgen-go"
)

//go:generate go install github.com/ydnar/wasm-tools-go/cmd/wit-bindgen-go
3 changes: 1 addition & 2 deletions loader/goroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"internal/": true,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/cm/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/task/": false,
Expand All @@ -251,8 +252,6 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"runtime/": false,
"sync/": true,
"testing/": true,
"vendor/": true,
"vendor/github.com/": false,
}

if goMinor >= 19 {
Expand Down
118 changes: 118 additions & 0 deletions src/internal/cm/abi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package cm

import "unsafe"

// 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) {
if unsafe.Sizeof(to) > unsafe.Sizeof(from) {
panic("reinterpret: size of to > from")
}
return *(*T)(unsafe.Pointer(&from))
}

// LowerString lowers a [string] into a pair of Core WebAssembly types.
//
// [string]: https://pkg.go.dev/builtin#string
func LowerString[S ~string](s S) (*byte, uint32) {
return unsafe.StringData(string(s)), uint32(len(s))
}

// 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 {
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) {
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)))
}

// BoolToU32 converts a value whose underlying type is [bool] into a [uint32].
// Used to lower a [bool] into a Core WebAssembly i32 as specified in the [Canonical ABI].
//
// [bool]: https://pkg.go.dev/builtin#bool
// [uint32]: https://pkg.go.dev/builtin#uint32
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func BoolToU32[B ~bool](v B) uint32 { return uint32(*(*uint8)(unsafe.Pointer(&v))) }

// U32ToBool converts a [uint32] into a [bool].
// Used to lift a Core WebAssembly i32 into a [bool] as specified in the [Canonical ABI].
//
// [uint32]: https://pkg.go.dev/builtin#uint32
// [bool]: https://pkg.go.dev/builtin#bool
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U32ToBool(v uint32) bool { tmp := uint8(v); return *(*bool)(unsafe.Pointer(&tmp)) }

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

// U32ToF32 maps the bits of a [uint32] into a [float32].
// Used to lift a Core WebAssembly i32 into a [float32] as specified in the [Canonical ABI].
//
// [uint32]: https://pkg.go.dev/builtin#uint32
// [float32]: https://pkg.go.dev/builtin#float32
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U32ToF32(v uint32) float32 { return *(*float32)(unsafe.Pointer(&v)) }

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

// U64ToF64 maps the bits of a [uint64] into a [float64].
// Used to lift a Core WebAssembly i64 into a [float64] as specified in the [Canonical ABI].
//
// [uint64]: https://pkg.go.dev/builtin#uint64
// [float64]: https://pkg.go.dev/builtin#float64
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U64ToF64(v uint64) float64 { return *(*float64)(unsafe.Pointer(&v)) }

// 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].
//
// [uint32]: https://pkg.go.dev/builtin#uint32
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func PointerToU32[T any](v *T) uint32 { return uint32(uintptr(unsafe.Pointer(v))) }

// U32ToPointer converts a [uint32] into a pointer of type *T.
// Used to lift a Core WebAssembly i32 into a pointer as specified in the [Canonical ABI].
//
// [uint32]: https://pkg.go.dev/builtin#uint32
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U32ToPointer[T any](v uint32) *T { return (*T)(unsafePointer(uintptr(v))) }

// PointerToU64 converts a pointer of type *T into a [uint64].
// Used to lower a pointer into a Core WebAssembly i64 as specified in the [Canonical ABI].
//
// [uint64]: https://pkg.go.dev/builtin#uint64
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func PointerToU64[T any](v *T) uint64 { return uint64(uintptr(unsafe.Pointer(v))) }

// U64ToPointer converts a [uint64] into a pointer of type *T.
// Used to lift a Core WebAssembly i64 into a pointer as specified in the [Canonical ABI].
//
// [uint64]: https://pkg.go.dev/builtin#uint64
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
func U64ToPointer[T any](v uint64) *T { return (*T)(unsafePointer(uintptr(v))) }

// Appease vet, see https://github.com/golang/go/issues/58625
func unsafePointer(p uintptr) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&p))
}
8 changes: 8 additions & 0 deletions src/internal/cm/docs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package cm contains types and functions for interfacing with the WebAssembly Component Model.
//
// The types in this package (such as [List], [Option], [Result], and [Variant]) are designed to match the memory layout
// of [Component Model] types as specified in the [Canonical ABI].
//
// [Component Model]: https://component-model.bytecodealliance.org/introduction.html
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#alignment
package cm
48 changes: 48 additions & 0 deletions src/internal/cm/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cm

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] }

// NewList returns a List[T] from data and len.
func NewList[T any](data *T, len uint) List[T] {
return List[T]{
list[T]{
data: data,
len: len,
},
}
}

// ToList returns a List[T] equivalent to the Go slice s.
// 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)))
}

// 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 {
data *T
len uint
}

// Slice returns a Go slice representing the List.
func (l list[T]) Slice() []T {
return unsafe.Slice(l.data, l.len)
}

// Data returns the data pointer for the list.
func (l list[T]) Data() *T {
return l.data
}

// Len returns the length of the list.
// TODO: should this return an int instead of a uint?
func (l list[T]) Len() uint {
return l.len
}
44 changes: 44 additions & 0 deletions src/internal/cm/option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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] }

// None returns an [Option] representing the none case,
// equivalent to the zero value.
func None[T any]() Option[T] {
return Option[T]{}
}

// Some returns an [Option] representing the some case.
func Some[T any](v T) Option[T] {
return Option[T]{
option[T]{
isSome: true,
some: v,
},
}
}

// option represents the internal representation of a Component Model option type.
// The first byte is a bool representing none or some,
// followed by storage for the associated type T.
type option[T any] struct {
isSome bool
some T
}

// None returns true if o represents the none case.
func (o *option[T]) None() bool {
return !o.isSome
}

// Some returns a non-nil *T if o represents the some case,
// or nil if o represents the none case.
func (o *option[T]) Some() *T {
if o.isSome {
return &o.some
}
return nil
}
21 changes: 21 additions & 0 deletions src/internal/cm/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cm

// Resource represents an opaque Component Model [resource handle].
// It is represented in the [Canonical ABI] as an 32-bit integer.
//
// [resource handle]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#handle-types
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
type Resource uint32

// Rep represents a Component Model [resource rep], the core representation type of a resource.
// It is represented in the [Canonical ABI] as an 32-bit integer.
//
// [resource rep]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#canon-resourcerep
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
type Rep uint32

// ResourceNone is a sentinel value indicating a null or uninitialized resource.
// This is a reserved value specified in the [Canonical ABI runtime state].
//
// [Canonical ABI runtime state]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#runtime-state
const ResourceNone = 0
Loading

0 comments on commit 87a8aaf

Please sign in to comment.