Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasi preview 2 support #4027

Open
wants to merge 14 commits into
base: dev
Choose a base branch
from
Open

Conversation

dgryski
Copy link
Member

@dgryski dgryski commented Dec 4, 2023

This PR adds -target=wasip2 support to TinyGo. It no longer depends on wasi-libc, but. has its own miniature libc that turns the calls into appropriate component calls.

@aykevl
Copy link
Member

aykevl commented Dec 5, 2023

Interesting!
Suggestion: use -target=wasip2 to more clearly specify the WASI version.

@dgryski dgryski force-pushed the dgryski/wasi-preview-2 branch 2 times, most recently from 399c173 to eeb8f09 Compare December 8, 2023 02:42
@dgryski
Copy link
Member Author

dgryski commented Dec 8, 2023

Now we just need to unstub the 29 calls in libc_wasip2.go with Go implementations of the associated C calls using preview2 calls under the hood.

@dgryski dgryski force-pushed the dgryski/wasi-preview-2 branch 2 times, most recently from 4288422 to 681281a Compare December 16, 2023 06:42
@ydnar
Copy link
Contributor

ydnar commented Feb 22, 2024

@dgryski the HOWTO in this PR might need to be updated to reflect the new build steps (and no need for a Preview 1 adapter!):

tinygo build -target=wasip2 -x -o main.wasm ./cmd/wasip2-test
wasm-tools component embed -w wasi:cli/command $(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm
wasm-tools component new embedded.wasm -o component.wasm
wasmtime run --wasm component-model component.wasm

@dgryski dgryski force-pushed the dgryski/wasi-preview-2 branch 2 times, most recently from 630f6e5 to dcea7bb Compare February 28, 2024 22:51
@dgryski dgryski force-pushed the dgryski/wasi-preview-2 branch 9 times, most recently from 567da72 to b2ae42f Compare April 2, 2024 21:34
@dgryski dgryski marked this pull request as ready for review April 2, 2024 21:37
@dgryski
Copy link
Member Author

dgryski commented Apr 2, 2024

This is now in a state where it's roughly equivalent to wasip1 support. I still plan to add networking support, but that can come in a later PR.

src/syscall/libc_wasip2.go Outdated Show resolved Hide resolved
src/syscall/libc_wasip2.go Outdated Show resolved Hide resolved
src/syscall/libc_wasip2.go Outdated Show resolved Hide resolved
Copy link
Contributor

@ydnar ydnar left a comment

Choose a reason for hiding this comment

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

Phone review, WIP

loader/goroot.go Outdated
@@ -240,6 +240,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/task/": false,
"internal/wasm/": false,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still need this?

loader/goroot.go Outdated Show resolved Hide resolved
main.go Outdated Show resolved Hide resolved
@dgryski
Copy link
Member Author

dgryski commented Apr 24, 2024

@deadprogram Yup, I'm looking at the linux.yml workflow now..

Copy link
Member

@deadprogram deadprogram left a comment

Choose a reason for hiding this comment

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

It is very large, but it is also the result of a lot of iterating and is covered by tests.

I say we merge and then continue from there.

@aykevl any comments?

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

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

Read through most of the PR, and skimmed libc_wasip2.go. Looks reasonable to me though I have a few concerns here and there.

And some more comments that I can't really do inline:

  • Can you add wasip2 to builder/builder_test.go? That way we can be sure the LLVM flags etc are the same between Clang and TinyGo.
  • I see a lot of places where you use //go:export. This is equivalent to //export, and deviates to from upstream Go. I'd prefer using //export everywhere.
    (I should never have added //go:export in the first place, I was just being lazy...)

GNUmakefile Outdated Show resolved Hide resolved
builder/build.go Outdated Show resolved Hide resolved
compiler/symbol.go Outdated Show resolved Hide resolved
compiler/symbol.go Show resolved Hide resolved
Comment on lines -19 to -25
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type string
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type *int32
//
//go:wasmimport modulename invalidparam
func invalidparam(a int, b string, c []byte, d *int32)
Copy link
Member

Choose a reason for hiding this comment

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

Why remove these tests? I think they're important.

Copy link
Contributor

@ydnar ydnar May 3, 2024

Choose a reason for hiding this comment

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

They're mostly no longer valid with the relaxed types in wasm args. We can re-add the slice test.

Copy link
Member

@aykevl aykevl May 9, 2024

Choose a reason for hiding this comment

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

I'd prefer if these tests were updated instead of removed altogether. ABIs are tricky to get right, and I'd like to have some tests for them.
For example: slices, maps, structs, and func values are still not allowed.

To make it really perfect, it'd be nice to add some tests to compiler/testdata/pragma.go to show that the compiler indeed produces the expected LLVM IR for the given types. Not a blocker though.

src/runtime/runtime_wasm_wasip2.go Show resolved Hide resolved
src/syscall/env_libc.go Outdated Show resolved Hide resolved
src/syscall/errno_wasip2.go Show resolved Hide resolved
src/syscall/syscall_libc_wasi.go Outdated Show resolved Hide resolved
src/syscall/libc_wasip2.go Outdated Show resolved Hide resolved
@dgryski
Copy link
Member Author

dgryski commented May 7, 2024

@aykevl PTAL. I think we've addressed everything.

@deadprogram
Copy link
Member

fix: remove extra wasm-tools file copies
@deadprogram
Copy link
Member

deadprogram commented May 7, 2024

@aykevl any other comments before we merge?

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

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

Having a proposal eases my worries about relaxing the //go:wasmimport rules, though I still have a few small things about the code that I'd like to see improved. (I'm careful with this because experience tells me that once the compiler allows something, it's very difficult to restrict it again in the future - it's much easier the other way round if needed!).

Other than that, it's mostly just minor nits.

Comment on lines +396 to +397
case *types.Struct:
return true
Copy link
Member

Choose a reason for hiding this comment

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

This is actually not part of golang/go#66984 anymore (though it is when it's a pointer-to-struct and pointer-to-array, this probably needs some more logic):

Supporting struct and [...]T by value

A previous version of this proposal included support for passing struct and [...]T types by value by expanding each field recursively into call parameters. This was removed in favor of a simpler initial implementation but could be readded if users require it.

Copy link
Member

@aykevl aykevl May 13, 2024

Choose a reason for hiding this comment

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

Also, now I think about it, we should definitely be stricter here and also check every field in the struct. Otherwise func(x *struct{field [2]int}) would be legal which it shouldn't be.

See: golang/go#66984 (comment)

Comment on lines +393 to +394
case types.String:
return true
Copy link
Member

Choose a reason for hiding this comment

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

Note that this works more or less by accident (because the way both Go and TinyGo represent strings is the most obvious way to do it so they match).

Copy link
Contributor

Choose a reason for hiding this comment

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

This also matches how WASI 0.2 represents strings (ptr, len pair)

compiler/symbol.go Show resolved Hide resolved
Comment on lines -19 to -25
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type string
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type *int32
//
//go:wasmimport modulename invalidparam
func invalidparam(a int, b string, c []byte, d *int32)
Copy link
Member

@aykevl aykevl May 9, 2024

Choose a reason for hiding this comment

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

I'd prefer if these tests were updated instead of removed altogether. ABIs are tricky to get right, and I'd like to have some tests for them.
For example: slices, maps, structs, and func values are still not allowed.

To make it really perfect, it'd be nice to add some tests to compiler/testdata/pragma.go to show that the compiler indeed produces the expected LLVM IR for the given types. Not a blocker though.

@@ -16,14 +16,6 @@ type Uint uint32
//go:wasmimport modulename validparam
func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint)
Copy link
Member

Choose a reason for hiding this comment

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

Might be a good idea to update this to add some new types (like string and *struct{}).

src/runtime/runtime_wasm_wasip2.go Show resolved Hide resolved
Comment on lines 14 to 17
// libc constructors
//
//export __wasm_call_ctors
func __wasm_call_ctors()
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer if it was removed then (though that's not a blocker, it just removes noise).

src/runtime/runtime_wasm_wasip2.go Outdated Show resolved Hide resolved
@dgryski
Copy link
Member Author

dgryski commented May 16, 2024

Is there anything else left unaddressed before we merge?

@aykevl
Copy link
Member

aykevl commented May 17, 2024

@dgryski yes there is, namely with //go:wasmimport. We are currently incompatible with the upstream proposal for loosening //go:wasmimport:

  • The upstream proposal doesn't allow passing structs as-is.
  • Also, the proposal now requires structs.HostLayout markers in every struct to ensure they match the underlying platform. The only thing TinyGo needs to do here is to check that the field is present: I haven't checked specifically but I'm pretty sure we already match the Canonical ABI for the in-memory layout.
  • We don't validate whether struct fields are allowed. So for example the following code would be allowed, even though it clearly is invalid:
    //go:wasmimport foo bar
    func bar(x *struct{a func()})

We could decide to deviate from the upstream proposal (especially when it comes to passing structs by value) but if we do that I'd like to see at least a good explanation for that (and the comment should be more than just "this reflects the relaxed type restrictions proposed here" because it doesn't).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants