Compare commits

...

63 Commits

Author SHA1 Message Date
Ayke van Laethem 2a76ceb7dd all: version v0.34.0 2024-10-25 18:22:40 +01:00
Ayke van Laethem 69263e7319 GNUmakefile: do not use the -v flag in go test
This makes it easier to find what actually went wrong in CI.
This flag was added in #4431, I think it was unintentional.
2024-10-25 17:01:35 +02:00
Damian Gryski 9a6397b325 runtime: bump markStackSize
Every time we overflow the stack, we have to do a full rescan of the heap.  Making this larger
means fewer overflows and thus fewer secondary+ heap scans.
2024-10-25 16:24:01 +02:00
sago35 b8420e78bb machine/usb/adc/midi: fix PitchBend 2024-10-25 06:25:49 +01:00
sago35 f0d523f778 machine/usb/adc/midi: clarify operator precedence 2024-10-25 06:25:49 +01:00
Damian Gryski 6e6507bf77 runtime: add gc layout info for some basic types 2024-10-24 13:07:17 +02:00
Ayke van Laethem b8fe75a9dd runtime: add support for os/signal
This adds support for enabling and listening to signals on Linux and
MacOS.
2024-10-23 12:25:27 +01:00
Ayke van Laethem 0f95b4102d wasm: use precise GC for WebAssembly (including WASI)
With a few small modifications, all the problems with `-gc=precise` in
WebAssembly seem to have been fixed.

I didn't do any performance measurements, but this is supposed to
improve GC performance.
2024-10-23 09:13:30 +01:00
Randy Reddig 24c11d4ba5 compiler: conform to latest iteration of wasm types proposal (#4501)
compiler: align with current wasm types proposal

https://github.com/golang/go/issues/66984

- Remove int and uint as allowed types in params, results, pointers, or struct fields
- Only allow small integers in pointers, arrays, or struct fields
- enforce structs.HostLayout usage per wasm types proposal
https://github.com/golang/go/issues/66984
- require go1.23 for structs.HostLayout
- use an interface to check if GoVersion() exists
This permits TinyGo to compile with Go 1.21.
- use goenv.Compare instead of WantGoVersion
- testdata/wasmexport: use int32 instead of int
- compiler/testdata: add structs.HostLayout
- compiler/testdata: improve tests for structs.HostLayout
2024-10-22 18:05:04 +02:00
Daniel Esteban 3dcac3b539 Add sponsor button to key repositories 2024-10-22 12:32:15 +01:00
Ayke van Laethem e615c25319 targets: add WaveShare ESP-C3-32S-Kit
I've had this board for a while now, but never added proper TinyGo
support. So here is a PR to do just that.
2024-10-22 11:21:48 +01:00
Ayke van Laethem b2fbbeb771 esp32c3: add smoke tests for a few boards
These boards probably haven't been working since the addition of I2C,
because they were missing some constants in the machine package.
2024-10-22 09:23:31 +01:00
Ayke van Laethem bcfe751f62 fe310: support GPIO PinInput
This is needed to support switching between input and output.
2024-10-21 18:30:31 +01:00
Randy Reddig a191326ea8 goenv: parse patch version, add func Compare to compare two Go version strings (#4536)
goenv: parse patch version, add func Compare to compare two Go version strings
* Parse tests
* add Compare function to compare two Go version strings
* goenv, builder: parse patch version in Go version string
2024-10-21 16:01:59 +02:00
Damian Gryski 23d3a31107 runtime: use unsafe.Slice for leveldb code 2024-10-19 15:16:30 -07:00
Damian Gryski 0dfa57ea04 runtime: use unsafe.Slice in tsip code 2024-10-19 15:16:30 -07:00
Ayke van Laethem 2f9e39e21c runtime: remove minSched hack for wasm
I am not entirely sure what it's doing (it seems related to js.FuncOf),
but tests still seem to pass when this code is removed. So let's remove
it.
2024-10-19 16:00:45 +01:00
Ayke van Laethem cd2bb8333d wasm: add test for js.FuncOf
While there are some browser tests, Node.js is just a lot better for
testing this kind of stuff because it's much faster and we don't need a
browser for this.
2024-10-19 16:00:45 +01:00
Ayke van Laethem 5e3c816373 ci: use macos-13 instead of macos-12 for amd64 builds
The macos-12 runner is being deprecated, so we have to switch to a new
runner: https://github.com/actions/runner-images/issues/10721

The next one is macos-13, which is still amd64.
2024-10-19 13:36:55 +01:00
Damian Gryski 951e50c06f compiler: mark stringFromRunes as nocapture/readonly 2024-10-19 11:02:54 +01:00
Damian Gryski 40c9c66c1d compiler: mark stringFromBytes as nocapture/readonly to help escape analysis
Fixes #4525
2024-10-19 11:02:54 +01:00
leongross 01dac8ba8e os/file_unix: add runtime function net.NewFile stub
Signed-off-by: leongross <leon.gross@9elements.com>
2024-10-18 18:37:49 +01:00
Ayke van Laethem ac5f84e3d7 builder: check for Go toolchain version used to compile TinyGo
This shows a much better error message for issues like this one:
https://github.com/NixOS/nixpkgs/pull/341170#issuecomment-2359237471

The new error message would be:

    cannot compile with Go toolchain version go1.23 (TinyGo was built using toolchain version go1.21.4)
2024-10-18 17:43:17 +02:00
Ayke van Laethem 9583439be4 loader: make sure we always return an error even without type errors
This issue was originally reported here:
https://github.com/NixOS/nixpkgs/pull/341170#issuecomment-2359237471

The fix here isn't a great fix, it turns the error message from this:

    # runtime/interrupt

into this:

    # runtime/interrupt
    package requires newer Go version go1.23

...so not great, because it doesn't show the real error message (which
is that TinyGo wasn't compiled with the right Go version). But at least
it gives a hint in the right direction.

It's difficult to test for this specific case, so I've left out testing
in this case (boo!)
2024-10-18 17:43:17 +02:00
Ayke van Laethem 2690b243ea main: make sure typecheck errors are correctly reported 2024-10-18 17:43:17 +02:00
Ayke van Laethem df724f5827 loader: don't panic when main package is not named 'main'
This can in fact happen in practice, so return an actual error message
instead.
2024-10-18 17:43:17 +02:00
Elias Naur 539cc5c47b transform: optimize range over []byte(string)
Fixes #2700
2024-10-18 17:42:20 +02:00
Ayke van Laethem 45cc5b58cd runtime: disallow defer in interrupts
This often doesn't work because there might not be a current task to
push the defer frame to. It will instead show an unhelpful nil pointer
dereference panic.

We could make this work with a separate defer stack for interrupts (as
if they were newly started goroutines) but that is difficult with
multiple interrupts happening at the same time (we shouldn't jump to a
previous interrupt in `panic()`!). So instead, disable defer altogether
in interrupts and adjust panic/recover accordingly.
2024-10-18 14:50:56 +01:00
Ayke van Laethem c6acaa981d builder: remove environment variables when invoking Clang
This is a problem on Guix, which sets C_INCLUDE_PATH that is not
affected by `-nostdlibinc`. And therefore it affects the build in
unintended ways.

Removing all environmental variables fixes this issue, and perhaps also
other issues caused by Clang being affected by environment variables.
2024-10-18 13:42:02 +01:00
Ayke van Laethem 4ef5109a07 wasm: add //go:wasmexport support to js/wasm
This adds support for //go:wasmexport with `-target=wasm` (in the
browser). This follows the //go:wasmexport proposal, meaning that
blocking functions are not allowed.

Both `-buildmode=default` and `-buildmode=c-shared` are supported. The
latter allows calling exported functions after `go.run()` has returned.
2024-10-18 10:07:21 +01:00
Ayke van Laethem 6016d0c739 main_test: refactor output comparison into separate function
This shouldn't affect anything, just make the code a bit better
(especially for the next commit).
2024-10-18 10:07:21 +01:00
Elias Naur 07d23c9d83 runtime: implement newcoro, coroswitch to support package iter 2024-10-18 10:44:20 +02:00
Randy Reddig d5f195387d internal/{cm,wasi}: regenerate WASI 0.2 bindings with wasm-tools-go v0.3.0 2024-10-17 17:30:33 +01:00
Randy Reddig a0d4ecb607 internal/wasm-tools: update wasm-tools-go to v0.3.0 2024-10-17 17:30:33 +01:00
Ayke van Laethem 505e68057d nix: use LLVM 18 instead of LLVM 17
This should fix some CI issues we're currently having.

Thanks to @sylv-io for discovering that we need to remove LLVM to avoid
an Xtensa backend linker error.
2024-10-17 14:21:58 +01:00
Damian Gryski 87c6e19921 runtime: add HeapAlloc to gc_leaking 2024-10-09 07:01:09 -07:00
deadprogram 62c1555aa8 targets: add bulk memory flags to wasm-unknown target since basically every runtime has it now
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-10-09 08:18:58 +01:00
Elias Naur e62fc43b05 crypto/x509/internal/macos: add package stub to build crypto/x509 on macOS 2024-10-08 08:54:35 +01:00
Damian Gryski 158be02ef7 builder: fix sizes 2024-10-07 19:23:49 -07:00
Damian Gryski fbb125131d runtime: track Memstats.HeapAlloc for gc_blocks 2024-10-07 19:23:49 -07:00
BCG c77ed8e50e Added mstats fields 2024-10-07 19:23:49 -07:00
Ayke d1b7238a36 Truly ignore //export when //go:wasmexport is used (#4500) 2024-10-05 18:53:38 +02:00
Randy Reddig 453a1d35c3 compiler, runtime: enable go:wasmexport for wasip2 (#4499)
* compiler: prefer go:wasmexport over go:export

* runtime, targets/wasip2: enable -buildmode=c-shared for wasip2

* runtime: rename import from wasi_run to wasiclirun (PR feedback)
2024-10-04 17:36:47 -07:00
Ayke 9da8b5c786 wasm: add //go:wasmexport support (#4451)
This adds support for the `//go:wasmexport` pragma as proposed here:
https://github.com/golang/go/issues/65199

It is currently implemented only for wasip1 and wasm-unknown, but it is
certainly possible to extend it to other targets like GOOS=js and
wasip2.
2024-10-04 15:33:47 -07:00
Damian Gryski 407889864f GNUmakefile: more stdlib packages 2024-10-04 08:09:10 +01:00
Damian Gryski e17daf165d GNUmakefile: add some more passing stdlib tests (#4492) 2024-10-03 16:03:08 -07:00
Ayke van Laethem 666d2bd501 builder: keep wasm temporary files
Don't rename them when -work is set, instead update result.Binary each
time and leave result.Executable be the linker output (as intended:
result.Executable should be the unmodified linker output).
2024-10-03 19:17:12 +01:00
Damian Gryski 9d14489547 TestWebAssembly: use wasm-unknown for panic=trap test 2024-10-02 12:40:07 +02:00
Damian Gryski f3dfe1d49e runtime: seed fastrand() with hardware randomness 2024-10-02 12:40:07 +02:00
Damian Gryski b3e1974c30 runtime: add maps.clone
Fixes #4382
2024-10-02 12:40:07 +02:00
Damian Gryski fa12450552 runtime: fix building with -tags=runtime_memhash_tsip 2024-10-02 12:40:07 +02:00
Damian Gryski b3c040e9f7 runtime: make map iteration less defined
Fixes #3726
2024-10-02 12:40:07 +02:00
leongross 52788e5826 main: rework usage (#4467)
main: rework usage

* remove unused switch case statement and improve/add command specific usage.
* limit help to 80 col width
* remove inconsistent ':'
* remove trailing spaces
* rmove spaces woth tabs
* reworkd build command

Signed-off-by: leongross <leon.gross@9elements.com>
2024-09-28 21:33:18 +02:00
leongross bcd4c6b658 builder: nits
remove unused job state enum, nits/reformatting

Signed-off-by: leongross <leon.gross@9elements.com>
2024-09-24 17:42:30 +01:00
Ayke van Laethem 37460ad60a compiler: support pragmas on generic functions 2024-09-23 09:41:44 +01:00
Ayke van Laethem dcca47f1f6 main: add -ldflags='-extldflags=...' support
This matches upstream Go. Example:

    $ go test -ldflags='-extldflags=-foobar' os
    # os.test
    /usr/local/go1.23.1/pkg/tool/linux_arm64/link: running gcc failed: exit status 1
    /usr/bin/gcc -s -o $WORK/b001/os.test -rdynamic /tmp/go-link-914594215/go.o /tmp/go-link-914594215/000000.o /tmp/go-link-914594215/000001.o /tmp/go-link-914594215/000002.o /tmp/go-link-914594215/000003.o /tmp/go-link-914594215/000004.o /tmp/go-link-914594215/000005.o /tmp/go-link-914594215/000006.o /tmp/go-link-914594215/000007.o /tmp/go-link-914594215/000008.o /tmp/go-link-914594215/000009.o /tmp/go-link-914594215/000010.o /tmp/go-link-914594215/000011.o /tmp/go-link-914594215/000012.o /tmp/go-link-914594215/000013.o /tmp/go-link-914594215/000014.o /tmp/go-link-914594215/000015.o /tmp/go-link-914594215/000016.o /tmp/go-link-914594215/000017.o /tmp/go-link-914594215/000018.o /tmp/go-link-914594215/000019.o /tmp/go-link-914594215/000020.o /tmp/go-link-914594215/000021.o -O2 -g -O2 -g -lresolv -O2 -g -lpthread -foobar
    gcc: error: unrecognized command-line option ‘-foobar’

    FAIL    os [build failed]
    FAIL

And TinyGo, with this patch:

    $ tinygo test -ldflags='-extldflags=-foobar' os
    FAIL    os      0.000s
    ld.lld: error: unknown argument '-foobar'

Also note that Go doesn't support the `-extldflags` directly (which was
previously the case with TinyGo):

    $ go test -extldflags='-foobar' os
    flag provided but not defined: -extldflags
    [...]
2024-09-18 12:43:05 +02:00
Damian Gryski 892efaec97 support -extldflags
Fixes #4320
2024-09-18 08:05:25 +02:00
leongross 84048f299f os/File: add stubs for os.File Deadlines (#4465)
os/File: add stubs for os.File Deadlines
* add os.SetDeadline, os.SetReadDeadline, os.SetWriteDeadline stubs for
posix files.
* deadline: add tests

Signed-off-by: leongross <leon.gross@9elements.com>
2024-09-17 17:26:22 +02:00
leongross a9bf981d92 Cgo add cbytes implementation (rebased version of #3318) (#4470)
cgo: added CBytes implementation
2024-09-17 16:12:57 +02:00
Randy Reddig d4729f92bd targets/wasip2: add wasmtime -S args to support network interfaces 2024-09-17 11:24:13 +02:00
Randy Reddig 5a014dd6a3 tinygo: add relative and absolute --dir options to wasmtime args (#4431)
main: add relative and absolute --dir options to wasmtime args
2024-09-17 09:24:23 +02:00
Ron Evans d948941d82 governance: add initial documentation for project governance (#4457)
governance: add initial attempt to document project governance

Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-09-13 11:24:10 +02:00
archie2x 5abf1e998d Fix #4421: Add -C DIR flag (#4422)
feature: Fix #4421: Add `-C DIR` flag

Signed-off-by: Roger Standridge <9526806+archie2x@users.noreply.github.com>
2024-09-13 07:05:44 +02:00
181 changed files with 6279 additions and 1253 deletions
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
open_collective: tinygo
+3 -3
View File
@@ -16,11 +16,11 @@ jobs:
name: build-macos
strategy:
matrix:
# macos-12: amd64 (oldest supported version as of 05-02-2024)
# macos-13: amd64 (oldest supported version as of 18-10-2024)
# macos-14: arm64 (oldest arm64 version)
os: [macos-12, macos-14]
os: [macos-13, macos-14]
include:
- os: macos-12
- os: macos-13
goarch: amd64
- os: macos-14
goarch: arm64
+5
View File
@@ -15,6 +15,11 @@ jobs:
nix-test:
runs-on: ubuntu-latest
steps:
- name: Uninstall system LLVM
# Hack to work around issue where we still include system headers for
# some reason.
# See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668
run: sudo apt-get remove llvm-18
- name: Checkout
uses: actions/checkout@v4
- name: Pull musl
+50
View File
@@ -1,3 +1,53 @@
0.34.0
---
* **general**
- fix `GOOS=wasip1` for `tinygo test`
- add `-C DIR` flag
- add initial documentation for project governance
- add `-ldflags='-extldflags=...'` support
- improve usage message with `tinygo help` and when passing invalid parameters
* **compiler**
- `builder`: remove environment variables when invoking Clang, to avoid the environment changing the behavior
- `builder`: check for the Go toolchain version used to compile TinyGo
- `cgo`: add `C.CBytes` implementation
- `compiler`: fix passing weirdly-padded structs as parameters to new goroutines
- `compiler`: support pragmas on generic functions
- `compiler`: do not let the slice buffer escape when casting a `[]byte` or `[]rune` to a string, to help escape analysis
- `compiler`: conform to the latest iteration of the wasm types proposal
- `loader`: don't panic when main package is not named 'main'
- `loader`: make sure we always return type checker errors even without type errors
- `transform`: optimize range over `[]byte(string)`
* **standard library**
- `crypto/x509`: add package stub to build crypto/x509 on macOS
- `machine/usb/adc/midi`: fix `PitchBend`
- `os`: add `Truncate` stub for baremetal
- `os`: add stubs for `os.File` deadlines
- `os`: add internal `net.newUnixFile` for the net package
- `runtime`: stub runtime_{Before,After}Exec for linkage
- `runtime`: randomize map accesses
- `runtime`: support `maps.Clone`
- `runtime`: add more fields to `MemStats`
- `runtime`: implement newcoro, coroswitch to support package iter
- `runtime`: disallow defer in interrupts
- `runtime`: add support for os/signal on Linux and MacOS
- `runtime`: add gc layout info for some basic types to help the precise GC
- `runtime`: bump GC mark stack size to avoid excessive heap rescans
* **targets**
- `darwin`: use Go standard library syscall package instead of a custom one
- `fe310`: support GPIO `PinInput`
- `mips`: fix compiler crash with GOMIPS=softfloat and defer
- `mips`: add big-endian (GOARCH=mips) support
- `mips`: use MIPS32 (instead of MIPS32R2) as the instruction set for wider compatibility
- `wasi`: add relative and absolute --dir options to wasmtime args
- `wasip2`: add wasmtime -S args to support network interfaces
- `wasm`: add `//go:wasmexport` support (for all WebAssembly targets)
- `wasm`: use precise instead of conservative GC for WebAssembly (including WASI)
- `wasm-unknown`: add bulk memory flags since basically every runtime has it now
* **boards**
- add RAKwireless RAK4631
- add WaveShare ESP-C3-32S-Kit
0.33.0
---
+39 -2
View File
@@ -293,7 +293,7 @@ tinygo: ## Build the TinyGo compiler
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags "byollvm osusergo" -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
test: wasi-libc check-nodejs-version
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags "byollvm osusergo" $(GOTESTPKGS)
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags "byollvm osusergo" $(GOTESTPKGS)
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
TEST_PACKAGES_SLOW = \
@@ -303,26 +303,34 @@ TEST_PACKAGES_SLOW = \
# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows
TEST_PACKAGES_FAST = \
cmp \
compress/lzw \
compress/zlib \
container/heap \
container/list \
container/ring \
crypto/des \
crypto/ecdsa \
crypto/elliptic \
crypto/md5 \
crypto/rc4 \
crypto/sha1 \
crypto/sha256 \
crypto/sha512 \
database/sql/driver \
debug/macho \
embed/internal/embedtest \
encoding \
encoding/ascii85 \
encoding/asn1 \
encoding/base32 \
encoding/base64 \
encoding/csv \
encoding/hex \
go/ast \
go/format \
go/scanner \
go/version \
hash \
hash/adler32 \
hash/crc64 \
@@ -357,11 +365,17 @@ endif
# archive/zip requires os.ReadAt, which is not yet supported on windows
# bytes requires mmap
# compress/flate appears to hang on wasi
# crypto/aes fails on wasi, needs panic()/recover()
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
# image requires recover(), which is not yet supported on wasi
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
# mime: fail on wasi; neds panic()/recover()
# mime/multipart: needs wasip1 syscall.FDFLAG_NONBLOCK
# mime/quotedprintable requires syscall.Faccessat
# net/mail: needs wasip1 syscall.FDFLAG_NONBLOCK
# net/ntextproto: needs wasip1 syscall.FDFLAG_NONBLOCK
# regexp/syntax: fails on wasip1; needs panic()/recover()
# strconv requires recover() which is not yet supported on wasi
# text/tabwriter requires recover(), which is not yet supported on wasi
# text/template/parse requires recover(), which is not yet supported on wasi
@@ -371,14 +385,20 @@ endif
TEST_PACKAGES_LINUX := \
archive/zip \
compress/flate \
crypto/aes \
crypto/hmac \
debug/dwarf \
debug/plan9obj \
image \
io/ioutil \
mime \
mime/multipart \
mime/quotedprintable \
net \
net/mail \
net/textproto \
os/user \
regexp/syntax \
strconv \
text/tabwriter \
text/template/parse
@@ -483,8 +503,17 @@ tinygo-baremetal:
# regression test for #2666: e.g. encoding/hex must pass on baremetal
$(TINYGO) test -target cortex-m-qemu encoding/hex
.PHONY: testchdir
testchdir:
# test 'build' command with{,out} -C argument
$(TINYGO) build -C tests/testing/chdir chdir.go && rm tests/testing/chdir/chdir
$(TINYGO) build ./tests/testing/chdir/chdir.go && rm chdir
# test 'run' command with{,out} -C argument
EXPECT_DIR=$(PWD)/tests/testing/chdir $(TINYGO) run -C tests/testing/chdir chdir.go
EXPECT_DIR=$(PWD) $(TINYGO) run ./tests/testing/chdir/chdir.go
.PHONY: smoketest
smoketest:
smoketest: testchdir
$(TINYGO) version
$(TINYGO) targets > /dev/null
# regression test for #2892
@@ -806,12 +835,20 @@ ifneq ($(XTENSA), 0)
$(TINYGO) build -size short -o test.bin -target mch2022 examples/machinetest
@$(MD5SUM) test.bin
endif
$(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit examples/blinky1
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=qtpy-esp32c3 examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=esp32-c3-devkit-rust-1 examples/blinky1
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/blinky1
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=makerfabs-esp32c3spi35 examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
+32
View File
@@ -0,0 +1,32 @@
TinyGo Team Members
===================
The team of humans who maintain TinyGo.
* **Purpose**: To maintain the community, code, documentation, and tools for the TinyGo compiler.
* **Board**: The group of people who share responsibility for key decisions for the TinyGo organization.
* **Majority Voting**: The board makes decisions by majority vote.
* **Membership**: The board elects its own members.
* **Do-ocracy**: Those who step forward to do a given task propose how it should be done. Then other interested people can make comments.
* **Proof of Work**: Power in decision-making is slightly weighted based on a participant's labor for the community.
* **Initiation**: We need to establish a procedure for how people join the team of maintainers.
* **Transparency**: Important information should be made publicly available, ideally in a way that allows for public comment.
* **Code of Conduct**: Participants agree to abide by the current project Code of Conduct.
## Members
* Ayke van Laethem (@aykevl)
* Daniel Esteban (@conejoninja)
* Ron Evans (@deadprogram)
* Damian Gryski (@dgryski)
* Masaaki Takasago (@sago35)
* Patricio Whittingslow (@soypat)
* Yurii Soldak (@ysoldak)
## Experimental
* **Monthly Meeting**: A monthly meeting for the team and any other interested participants.
Duration: 1 hour
Facilitation: @deadprogram
Schedule: See https://github.com/tinygo-org/tinygo/wiki/Meetings for more information
+22 -16
View File
@@ -197,6 +197,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
ABI: config.ABI(),
GOOS: config.GOOS(),
GOARCH: config.GOARCH(),
BuildMode: config.BuildMode(),
CodeModel: config.CodeModel(),
RelocationModel: config.RelocationModel(),
SizeLevel: sizeLevel,
@@ -649,6 +650,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
result.Binary = result.Executable // final file
ldflags := append(config.LDFlags(), "-o", result.Executable)
if config.Options.BuildMode == "c-shared" {
if !strings.HasPrefix(config.Triple(), "wasm32-") {
return result, fmt.Errorf("buildmode c-shared is only supported on wasm at the moment")
}
ldflags = append(ldflags, "--no-entry")
}
// Add compiler-rt dependency if needed. Usually this is a simple load from
// a cache.
if config.Target.RTLib == "compiler-rt" {
@@ -823,19 +831,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
args = append(args, "--asyncify")
}
exeunopt := result.Executable
if config.Options.Work {
// Keep the work direction around => don't overwrite the .wasm binary with the optimized version
exeunopt += ".pre-wasm-opt"
os.Rename(result.Executable, exeunopt)
}
inputFile := result.Binary
result.Binary = result.Executable + ".wasmopt"
args = append(args,
opt,
"-g",
exeunopt,
"--output", result.Executable,
inputFile,
"--output", result.Binary,
)
wasmopt := goenv.Get("WASMOPT")
@@ -865,13 +867,15 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
// wasm-tools component embed -w wasi:cli/command
// $$(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm
componentEmbedInputFile := result.Binary
result.Binary = result.Executable + ".wasm-component-embed"
args := []string{
"component",
"embed",
"-w", witWorld,
witPackage,
result.Executable,
"-o", result.Executable,
componentEmbedInputFile,
"-o", result.Binary,
}
wasmtools := goenv.Get("WASMTOOLS")
@@ -884,15 +888,17 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
err := cmd.Run()
if err != nil {
return fmt.Errorf("wasm-tools failed: %w", err)
return fmt.Errorf("`wasm-tools component embed` failed: %w", err)
}
// wasm-tools component new embedded.wasm -o component.wasm
componentNewInputFile := result.Binary
result.Binary = result.Executable + ".wasm-component-new"
args = []string{
"component",
"new",
result.Executable,
"-o", result.Executable,
componentNewInputFile,
"-o", result.Binary,
}
if config.Options.PrintCommands != nil {
@@ -904,7 +910,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
err = cmd.Run()
if err != nil {
return fmt.Errorf("wasm-tools failed: %w", err)
return fmt.Errorf("`wasm-tools component new` failed: %w", err)
}
}
-12
View File
@@ -3,7 +3,6 @@ package builder
import (
"errors"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
@@ -76,14 +75,3 @@ func LookupCommand(name string) (string, error) {
}
return "", errors.New("none of these commands were found in your $PATH: " + strings.Join(commands[name], " "))
}
func execCommand(name string, args ...string) error {
name, err := LookupCommand(name)
if err != nil {
return err
}
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
+22 -4
View File
@@ -2,6 +2,7 @@ package builder
import (
"fmt"
"runtime"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
@@ -23,20 +24,37 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
spec.OpenOCDCommands = options.OpenOCDCommands
}
major, minor, err := goenv.GetGorootVersion()
// Version range supported by TinyGo.
const minorMin = 19
const minorMax = 23
// Check that we support this Go toolchain version.
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
if err != nil {
return nil, err
}
if major != 1 || minor < 19 || minor > 23 {
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
// Note: when this gets updated, also update the Go compatibility matrix:
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", major, minor)
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", gorootMajor, gorootMinor)
}
// Check that the Go toolchain version isn't too new, if we haven't been
// compiled with the latest Go version.
// This may be a bit too aggressive: if the newer version doesn't change the
// Go language we will most likely be able to compile it.
buildMajor, buildMinor, _, err := goenv.Parse(runtime.Version())
if err != nil {
return nil, err
}
if buildMajor != 1 || buildMinor < gorootMinor {
return nil, fmt.Errorf("cannot compile with Go toolchain version go%d.%d (TinyGo was built using toolchain version %s)", gorootMajor, gorootMinor, runtime.Version())
}
return &compileopts.Config{
Options: options,
Target: spec,
GoMinorVersion: minor,
GoMinorVersion: gorootMinor,
TestConfig: options.TestConfig,
}, nil
}
+6 -16
View File
@@ -17,14 +17,6 @@ import (
// concurrency or performance issues.
const jobRunnerDebug = false
type jobState uint8
const (
jobStateQueued jobState = iota // not yet running
jobStateRunning // running
jobStateFinished // finished running
)
// compileJob is a single compiler job, comparable to a single Makefile target.
// It is used to orchestrate various compiler tasks that can be run in parallel
// but that have dependencies and thus have limitations in how they can be run.
@@ -55,12 +47,11 @@ func dummyCompileJob(result string) *compileJob {
// ordered as such in the job dependencies.
func runJobs(job *compileJob, sema chan struct{}) error {
if sema == nil {
// Have a default, if the semaphore isn't set. This is useful for
// tests.
// Have a default, if the semaphore isn't set. This is useful for tests.
sema = make(chan struct{}, runtime.NumCPU())
}
if cap(sema) == 0 {
return errors.New("cannot 0 jobs at a time")
return errors.New("cannot run 0 jobs at a time")
}
// Create a slice of jobs to run, where all dependencies are run in order.
@@ -81,10 +72,10 @@ func runJobs(job *compileJob, sema chan struct{}) error {
waiting := make(map[*compileJob]map[*compileJob]struct{}, len(jobs))
dependents := make(map[*compileJob][]*compileJob, len(jobs))
jidx := make(map[*compileJob]int)
compileJobs := make(map[*compileJob]int)
var ready intHeap
for i, job := range jobs {
jidx[job] = i
compileJobs[job] = i
if len(job.dependencies) == 0 {
// This job is ready to run.
ready.Push(i)
@@ -105,8 +96,7 @@ func runJobs(job *compileJob, sema chan struct{}) error {
// Create a channel to accept notifications of completion.
doneChan := make(chan *compileJob)
// Send each job in the jobs slice to a worker, taking care of job
// dependencies.
// Send each job in the jobs slice to a worker, taking care of job dependencies.
numRunningJobs := 0
var totalTime time.Duration
start := time.Now()
@@ -156,7 +146,7 @@ func runJobs(job *compileJob, sema chan struct{}) error {
delete(wait, completed)
if len(wait) == 0 {
// This job is now ready to run.
ready.Push(jidx[j])
ready.Push(compileJobs[j])
delete(waiting, j)
}
}
+1
View File
@@ -128,6 +128,7 @@ var libMusl = Library{
"mman/*.c",
"math/*.c",
"multibyte/*.c",
"signal/" + arch + "/*.s",
"signal/*.c",
"stdio/*.c",
"string/*.c",
+3 -3
View File
@@ -41,9 +41,9 @@ func TestBinarySize(t *testing.T) {
// This is a small number of very diverse targets that we want to test.
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 4484, 280, 0, 2252},
{"microbit", "examples/serial", 2732, 388, 8, 2256},
{"wioterminal", "examples/pininterrupt", 6016, 1484, 116, 6816},
{"hifive1b", "examples/echo", 4568, 280, 0, 2268},
{"microbit", "examples/serial", 2868, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 6104, 1484, 116, 6832},
// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
+19 -6
View File
@@ -14,16 +14,29 @@ import (
// runCCompiler invokes a C compiler with the given arguments.
func runCCompiler(flags ...string) error {
// Find the right command to run Clang.
var cmd *exec.Cmd
if hasBuiltinTools {
// Compile this with the internal Clang compiler.
cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
cmd = exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
} else {
// Compile this with an external invocation of the Clang compiler.
name, err := LookupCommand("clang")
if err != nil {
return err
}
cmd = exec.Command(name, flags...)
}
// Compile this with an external invocation of the Clang compiler.
return execCommand("clang", flags...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// Make sure the command doesn't use any environmental variables.
// Most importantly, it should not use C_INCLUDE_PATH and the like. But
// removing all environmental variables also works.
cmd.Env = []string{}
return cmd.Run()
}
// link invokes a linker with the given name and flags.
+8 -1
View File
@@ -162,6 +162,13 @@ func __GoBytes(unsafe.Pointer, uintptr) []byte
func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func __CBytes([]byte) unsafe.Pointer
func CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
`
// Process extracts `import "C"` statements from the AST, parses the comment
@@ -218,7 +225,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
switch decl := decl.(type) {
case *ast.FuncDecl:
switch decl.Name.Name {
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes":
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes":
// Adjust the name to have a "C." prefix so it is correctly
// resolved.
decl.Name.Name = "C." + decl.Name.Name
+7
View File
@@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
type (
C.char uint8
C.schar int8
+7
View File
@@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
type (
C.char uint8
C.schar int8
+7
View File
@@ -44,6 +44,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
type (
C.char uint8
C.schar int8
+7
View File
@@ -29,6 +29,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
type (
C.char uint8
C.schar int8
+7
View File
@@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
type (
C.char uint8
C.schar int8
+7
View File
@@ -24,6 +24,13 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
return C.__GoBytes(ptr, uintptr(length))
}
//go:linkname C.__CBytes runtime.cgo_CBytes
func C.__CBytes([]byte) unsafe.Pointer
func C.CBytes(b []byte) unsafe.Pointer {
return C.__CBytes(b)
}
type (
C.char uint8
C.schar int8
+21
View File
@@ -33,6 +33,17 @@ func (c *Config) CPU() string {
return c.Target.CPU
}
// The current build mode (like the `-buildmode` command line flag).
func (c *Config) BuildMode() string {
if c.Options.BuildMode != "" {
return c.Options.BuildMode
}
if c.Target.BuildMode != "" {
return c.Target.BuildMode
}
return "default"
}
// Features returns a list of features this CPU supports. For example, for a
// RISC-V processor, that could be "+a,+c,+m". For many targets, an empty list
// will be returned.
@@ -395,6 +406,16 @@ func (c *Config) LDFlags() []string {
if c.Target.LinkerScript != "" {
ldflags = append(ldflags, "-T", c.Target.LinkerScript)
}
if c.Options.ExtLDFlags != "" {
ext, err := shlex.Split(c.Options.ExtLDFlags)
if err != nil {
// if shlex can't split it, pass it as-is and let the external linker complain
ext = []string{c.Options.ExtLDFlags}
}
ldflags = append(ldflags, ext...)
}
return ldflags
}
+11
View File
@@ -8,6 +8,7 @@ import (
)
var (
validBuildModeOptions = []string{"default", "c-shared"}
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
@@ -26,6 +27,7 @@ type Options struct {
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
Directory string // working dir, leave it unset to use the current working dir
Target string
BuildMode string // -buildmode flag
Opt string
GC string
PanicStrategy string
@@ -56,10 +58,19 @@ type Options struct {
Timeout time.Duration
WITPackage string // pass through to wasm-tools component embed invocation
WITWorld string // pass through to wasm-tools component embed -w option
ExtLDFlags string
}
// Verify performs a validation on the given options, raising an error if options are not valid.
func (o *Options) Verify() error {
if o.BuildMode != "" {
valid := isInArray(validBuildModeOptions, o.BuildMode)
if !valid {
return fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,
o.BuildMode,
strings.Join(validBuildModeOptions, ", "))
}
}
if o.GC != "" {
valid := isInArray(validGCOptions, o.GC)
if !valid {
+5 -2
View File
@@ -32,6 +32,7 @@ type TargetSpec struct {
GOARCH string `json:"goarch,omitempty"`
SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc)
BuildTags []string `json:"build-tags,omitempty"`
BuildMode string `json:"buildmode,omitempty"` // default build mode (if nothing specified)
GC string `json:"gc,omitempty"`
Scheduler string `json:"scheduler,omitempty"`
Serial string `json:"serial,omitempty"` // which serial output to use (uart, usb, none)
@@ -390,7 +391,8 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
)
spec.ExtraFiles = append(spec.ExtraFiles,
"src/runtime/os_darwin.c",
"src/runtime/runtime_unix.c")
"src/runtime/runtime_unix.c",
"src/runtime/signal.c")
case "linux":
spec.Linker = "ld.lld"
spec.RTLib = "compiler-rt"
@@ -411,7 +413,8 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
}
spec.ExtraFiles = append(spec.ExtraFiles,
"src/runtime/runtime_unix.c")
"src/runtime/runtime_unix.c",
"src/runtime/signal.c")
case "windows":
spec.Linker = "ld.lld"
spec.Libc = "mingw-w64"
+6
View File
@@ -44,6 +44,7 @@ type Config struct {
ABI string
GOOS string
GOARCH string
BuildMode string
CodeModel string
RelocationModel string
SizeLevel int
@@ -1384,6 +1385,11 @@ func (b *builder) createFunction() {
b.llvmFn.SetLinkage(llvm.InternalLinkage)
b.createFunction()
}
// Create wrapper function that can be called externally.
if b.info.wasmExport != "" {
b.createWasmExport()
}
}
// posser is an interface that's implemented by both ssa.Value and
+253 -20
View File
@@ -7,6 +7,7 @@ import (
"go/token"
"go/types"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm"
)
@@ -101,7 +102,7 @@ func (b *builder) createGo(instr *ssa.Go) {
paramBundle := b.emitPointerPack(params)
var stackSize llvm.Value
callee := b.createGoroutineStartWrapper(funcType, funcPtr, prefix, hasContext, instr.Pos())
callee := b.createGoroutineStartWrapper(funcType, funcPtr, prefix, hasContext, false, instr.Pos())
if b.AutomaticStackSize {
// The stack size is not known until after linking. Call a dummy
// function that will be replaced with a load from a special ELF
@@ -121,6 +122,147 @@ func (b *builder) createGo(instr *ssa.Go) {
b.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.dataPtrType)}, "")
}
// Create an exported wrapper function for functions with the //go:wasmexport
// pragma. This wrapper function is quite complex when the scheduler is enabled:
// it needs to start a new goroutine each time the exported function is called.
func (b *builder) createWasmExport() {
pos := b.info.wasmExportPos
if b.info.exported {
// //export really shouldn't be used anymore when //go:wasmexport is
// available, because //go:wasmexport is much better defined.
b.addError(pos, "cannot use //export and //go:wasmexport at the same time")
return
}
const suffix = "#wasmexport"
// Declare the exported function.
paramTypes := b.llvmFnType.ParamTypes()
exportedFnType := llvm.FunctionType(b.llvmFnType.ReturnType(), paramTypes[:len(paramTypes)-1], false)
exportedFn := llvm.AddFunction(b.mod, b.fn.RelString(nil)+suffix, exportedFnType)
b.addStandardAttributes(exportedFn)
llvmutil.AppendToGlobal(b.mod, "llvm.used", exportedFn)
exportedFn.AddFunctionAttr(b.ctx.CreateStringAttribute("wasm-export-name", b.info.wasmExport))
// Create a builder for this wrapper function.
builder := newBuilder(b.compilerContext, b.ctx.NewBuilder(), b.fn)
defer builder.Dispose()
// Define this function as a separate function in DWARF
if b.Debug {
if b.fn.Syntax() != nil {
// Create debug info file if needed.
pos := b.program.Fset.Position(pos)
builder.difunc = builder.attachDebugInfoRaw(b.fn, exportedFn, suffix, pos.Filename, pos.Line)
}
builder.setDebugLocation(pos)
}
// Create a single basic block inside of it.
bb := llvm.AddBasicBlock(exportedFn, "entry")
builder.SetInsertPointAtEnd(bb)
// Insert an assertion to make sure this //go:wasmexport function is not
// called at a time when it is not allowed (for example, before the runtime
// is initialized).
builder.createRuntimeCall("wasmExportCheckRun", nil, "")
if b.Scheduler == "none" {
// When the scheduler has been disabled, this is really trivial: just
// call the function.
params := exportedFn.Params()
params = append(params, llvm.ConstNull(b.dataPtrType)) // context parameter
retval := builder.CreateCall(b.llvmFnType, b.llvmFn, params, "")
if b.fn.Signature.Results() == nil {
builder.CreateRetVoid()
} else {
builder.CreateRet(retval)
}
} else {
// The scheduler is enabled, so we need to start a new goroutine, wait
// for it to complete, and read the result value.
// Build a function that looks like this:
//
// func foo#wasmexport(param0, param1, ..., paramN) {
// var state *stateStruct
//
// // 'done' must be explicitly initialized ('state' is not zeroed)
// state.done = false
//
// // store the parameters in the state object
// state.param0 = param0
// state.param1 = param1
// ...
// state.paramN = paramN
//
// // create a goroutine and push it to the runqueue
// task.start(uintptr(gowrapper), &state)
//
// // run the scheduler
// runtime.wasmExportRun(&state.done)
//
// // if there is a return value, load it and return
// return state.result
// }
hasReturn := b.fn.Signature.Results() != nil
// Build the state struct type.
// It stores the function parameters, the 'done' flag, and reserves
// space for a return value if needed.
stateFields := exportedFnType.ParamTypes()
numParams := len(stateFields)
stateFields = append(stateFields, b.ctx.Int1Type()) // 'done' field
if hasReturn {
stateFields = append(stateFields, b.llvmFnType.ReturnType())
}
stateStruct := b.ctx.StructType(stateFields, false)
// Allocate the state struct on the stack.
statePtr := builder.CreateAlloca(stateStruct, "status")
// Initialize the 'done' field.
doneGEP := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), uint64(numParams), false),
}, "done.gep")
builder.CreateStore(llvm.ConstNull(b.ctx.Int1Type()), doneGEP)
// Store all parameters in the state object.
for i, param := range exportedFn.Params() {
gep := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
}, "")
builder.CreateStore(param, gep)
}
// Create a new goroutine and add it to the runqueue.
wrapper := b.createGoroutineStartWrapper(b.llvmFnType, b.llvmFn, "", false, true, pos)
stackSize := llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false)
taskStartFnType, taskStartFn := builder.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function))
builder.createCall(taskStartFnType, taskStartFn, []llvm.Value{wrapper, statePtr, stackSize, llvm.Undef(b.dataPtrType)}, "")
// Run the scheduler.
builder.createRuntimeCall("wasmExportRun", []llvm.Value{doneGEP}, "")
// Read the return value (if any) and return to the caller of the
// //go:wasmexport function.
if hasReturn {
gep := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), uint64(numParams)+1, false),
}, "")
retval := builder.CreateLoad(b.llvmFnType.ReturnType(), gep, "retval")
builder.CreateRet(retval)
} else {
builder.CreateRetVoid()
}
}
}
// createGoroutineStartWrapper creates a wrapper for the task-based
// implementation of goroutines. For example, to call a function like this:
//
@@ -144,7 +286,7 @@ func (b *builder) createGo(instr *ssa.Go) {
// to last parameter of the function) is used for this wrapper. If hasContext is
// false, the parameter bundle is assumed to have no context parameter and undef
// is passed instead.
func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext bool, pos token.Pos) llvm.Value {
func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext, isWasmExport bool, pos token.Pos) llvm.Value {
var wrapper llvm.Value
b := &builder{
@@ -162,14 +304,18 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
if !fn.IsAFunction().IsNil() {
// See whether this wrapper has already been created. If so, return it.
name := fn.Name()
wrapper = c.mod.NamedFunction(name + "$gowrapper")
wrapperName := name + "$gowrapper"
if isWasmExport {
wrapperName += "-wasmexport"
}
wrapper = c.mod.NamedFunction(wrapperName)
if !wrapper.IsNil() {
return llvm.ConstPtrToInt(wrapper, c.uintptrType)
}
// Create the wrapper.
wrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.dataPtrType}, false)
wrapper = llvm.AddFunction(c.mod, name+"$gowrapper", wrapperType)
wrapper = llvm.AddFunction(c.mod, wrapperName, wrapperType)
c.addStandardAttributes(wrapper)
wrapper.SetLinkage(llvm.LinkOnceODRLinkage)
wrapper.SetUnnamedAddr(true)
@@ -199,23 +345,110 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
}
// Create the list of params for the call.
paramTypes := fnType.ParamTypes()
if !hasContext {
paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter
}
params := b.emitPointerUnpack(wrapper.Param(0), paramTypes)
if !hasContext {
params = append(params, llvm.Undef(c.dataPtrType)) // add dummy context parameter
}
if !isWasmExport {
// Regular 'go' instruction.
// Create the call.
b.CreateCall(fnType, fn, params, "")
// Create the list of params for the call.
paramTypes := fnType.ParamTypes()
if !hasContext {
paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter
}
if c.Scheduler == "asyncify" {
b.CreateCall(deadlockType, deadlock, []llvm.Value{
llvm.Undef(c.dataPtrType),
}, "")
params := b.emitPointerUnpack(wrapper.Param(0), paramTypes)
if !hasContext {
params = append(params, llvm.Undef(c.dataPtrType)) // add dummy context parameter
}
// Create the call.
b.CreateCall(fnType, fn, params, "")
if c.Scheduler == "asyncify" {
b.CreateCall(deadlockType, deadlock, []llvm.Value{
llvm.Undef(c.dataPtrType),
}, "")
}
} else {
// Goroutine started from a //go:wasmexport pragma.
// The function looks like this:
//
// func foo$gowrapper-wasmexport(state *stateStruct) {
// // load values
// param0 := state.params[0]
// param1 := state.params[1]
//
// // call wrapped functions
// result := foo(param0, param1, ...)
//
// // store result value (if there is any)
// state.result = result
//
// // finish exported function
// state.done = true
// runtime.wasmExportExit()
// }
//
// The state object here looks like:
//
// struct state {
// param0
// param1
// param* // etc
// done bool
// result returnType
// }
returnType := fnType.ReturnType()
hasReturn := returnType != b.ctx.VoidType()
statePtr := wrapper.Param(0)
// Create the state struct (it must match the type in createWasmExport).
stateFields := fnType.ParamTypes()
numParams := len(stateFields) - 1
stateFields = stateFields[:numParams:numParams] // strip 'context' parameter
stateFields = append(stateFields, c.ctx.Int1Type()) // 'done' bool
if hasReturn {
stateFields = append(stateFields, returnType)
}
stateStruct := b.ctx.StructType(stateFields, false)
// Extract parameters from the state object, and call the function
// that's being wrapped.
var callParams []llvm.Value
for i := 0; i < numParams; i++ {
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
}, "")
param := b.CreateLoad(stateFields[i], gep, "")
callParams = append(callParams, param)
}
callParams = append(callParams, llvm.ConstNull(c.dataPtrType)) // add 'context' parameter
result := b.CreateCall(fnType, fn, callParams, "")
// Store the return value back into the shared state.
// Unlike regular goroutines, these special //go:wasmexport
// goroutines can return a value.
if hasReturn {
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
llvm.ConstInt(c.ctx.Int32Type(), uint64(numParams)+1, false),
}, "result.ptr")
b.CreateStore(result, gep)
}
// Mark this function as having finished executing.
// This is important so the runtime knows the exported function
// didn't block.
doneGEP := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
llvm.ConstInt(c.ctx.Int32Type(), uint64(numParams), false),
}, "done.gep")
b.CreateStore(llvm.ConstInt(b.ctx.Int1Type(), 1, false), doneGEP)
// Call back into the runtime. This will exit the goroutine, switch
// back to the scheduler, which will in turn return from the
// //go:wasmexport function.
b.createRuntimeCall("wasmExportExit", nil, "")
}
} else {
@@ -297,5 +530,5 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
}
// Return a ptrtoint of the wrapper, not the function itself.
return b.CreatePtrToInt(wrapper, c.uintptrType, "")
return llvm.ConstPtrToInt(wrapper, c.uintptrType)
}
+182 -103
View File
@@ -12,6 +12,7 @@ import (
"strings"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/loader"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm"
@@ -23,15 +24,17 @@ import (
// The linkName value contains a valid link name, even if //go:linkname is not
// present.
type functionInfo struct {
wasmModule string // go:wasm-module
wasmName string // wasm-export-name or wasm-import-name in the IR
linkName string // go:linkname, go:export - the IR function name
section string // go:section - object file section name
exported bool // go:export, CGo
interrupt bool // go:interrupt
nobounds bool // go:nobounds
variadic bool // go:variadic (CGo only)
inline inlineType // go:inline
wasmModule string // go:wasm-module
wasmName string // wasm-export-name or wasm-import-name in the IR
wasmExport string // go:wasmexport is defined (export is unset, this adds an exported wrapper)
wasmExportPos token.Pos // position of //go:wasmexport comment
linkName string // go:linkname, go:export - the IR function name
section string // go:section - object file section name
exported bool // go:export, CGo
interrupt bool // go:interrupt
nobounds bool // go:nobounds
variadic bool // go:variadic (CGo only)
inline inlineType // go:inline
}
type inlineType int
@@ -170,6 +173,12 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
case "runtime.stringFromBytes":
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
case "runtime.stringFromRunes":
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
case "runtime.trackPointer":
// This function is necessary for tracking pointers on the stack in a
// portable way (see gc_stack_portable.go). Indicate to the optimizer
@@ -241,8 +250,22 @@ func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
// Pick the default linkName.
linkName: f.RelString(nil),
}
// Check for a few runtime functions that are treated specially.
if info.linkName == "runtime.wasmEntryReactor" && c.BuildMode == "c-shared" {
info.linkName = "_initialize"
info.wasmName = "_initialize"
info.exported = true
}
if info.linkName == "runtime.wasmEntryCommand" && c.BuildMode == "default" {
info.linkName = "_start"
info.wasmName = "_start"
info.exported = true
}
// Check for //go: pragmas, which may change the link name (among others).
c.parsePragmas(&info, f)
c.functionInfos[f] = info
return info
}
@@ -250,126 +273,164 @@ func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
// parsePragmas is used by getFunctionInfo to parse function pragmas such as
// //export or //go:noinline.
func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
if f.Syntax() == nil {
syntax := f.Syntax()
if f.Origin() != nil {
syntax = f.Origin().Syntax()
}
if syntax == nil {
return
}
if decl, ok := f.Syntax().(*ast.FuncDecl); ok && decl.Doc != nil {
// Read all pragmas of this function.
var pragmas []*ast.Comment
hasWasmExport := false
if decl, ok := syntax.(*ast.FuncDecl); ok && decl.Doc != nil {
for _, comment := range decl.Doc.List {
text := comment.Text
if strings.HasPrefix(text, "//export ") {
// Rewrite '//export' to '//go:export' for compatibility with
// gc.
text = "//go:" + text[2:]
if strings.HasPrefix(text, "//go:") || strings.HasPrefix(text, "//export ") {
pragmas = append(pragmas, comment)
if strings.HasPrefix(comment.Text, "//go:wasmexport ") {
hasWasmExport = true
}
}
if !strings.HasPrefix(text, "//go:") {
}
}
// Parse each pragma.
for _, comment := range pragmas {
parts := strings.Fields(comment.Text)
switch parts[0] {
case "//export", "//go:export":
if len(parts) != 2 {
continue
}
if hasWasmExport {
// //go:wasmexport overrides //export.
continue
}
parts := strings.Fields(text)
switch parts[0] {
case "//go:export":
if len(parts) != 2 {
continue
}
info.linkName = parts[1]
info.wasmName = info.linkName
info.exported = true
case "//go:interrupt":
if hasUnsafeImport(f.Pkg.Pkg) {
info.interrupt = true
}
case "//go:wasm-module":
// Alternative comment for setting the import module.
// This is deprecated, use //go:wasmimport instead.
if len(parts) != 2 {
continue
}
info.wasmModule = parts[1]
case "//go:wasmimport":
// Import a WebAssembly function, for example a WASI function.
// Original proposal: https://github.com/golang/go/issues/38248
// Allow globally: https://github.com/golang/go/issues/59149
if len(parts) != 3 {
continue
}
c.checkWasmImport(f, comment.Text)
info.exported = true
info.wasmModule = parts[1]
info.wasmName = parts[2]
case "//go:inline":
info.inline = inlineHint
case "//go:noinline":
info.linkName = parts[1]
info.wasmName = info.linkName
info.exported = true
case "//go:interrupt":
if hasUnsafeImport(f.Pkg.Pkg) {
info.interrupt = true
}
case "//go:wasm-module":
// Alternative comment for setting the import module.
// This is deprecated, use //go:wasmimport instead.
if len(parts) != 2 {
continue
}
info.wasmModule = parts[1]
case "//go:wasmimport":
// Import a WebAssembly function, for example a WASI function.
// Original proposal: https://github.com/golang/go/issues/38248
// Allow globally: https://github.com/golang/go/issues/59149
if len(parts) != 3 {
continue
}
if f.Blocks != nil {
// Defined functions cannot be exported.
c.addError(f.Pos(), "can only use //go:wasmimport on declarations")
continue
}
c.checkWasmImportExport(f, comment.Text)
info.exported = true
info.wasmModule = parts[1]
info.wasmName = parts[2]
case "//go:wasmexport":
if f.Blocks == nil {
c.addError(f.Pos(), "can only use //go:wasmexport on definitions")
continue
}
if len(parts) != 2 {
c.addError(f.Pos(), fmt.Sprintf("expected one parameter to //go:wasmimport, not %d", len(parts)-1))
continue
}
name := parts[1]
if name == "_start" || name == "_initialize" {
c.addError(f.Pos(), fmt.Sprintf("//go:wasmexport does not allow %#v", name))
continue
}
if c.BuildMode != "c-shared" && f.RelString(nil) == "main.main" {
c.addError(f.Pos(), fmt.Sprintf("//go:wasmexport does not allow main.main to be exported with -buildmode=%s", c.BuildMode))
continue
}
if c.archFamily() != "wasm32" {
c.addError(f.Pos(), "//go:wasmexport is only supported on wasm")
}
c.checkWasmImportExport(f, comment.Text)
info.wasmExport = name
info.wasmExportPos = comment.Slash
case "//go:inline":
info.inline = inlineHint
case "//go:noinline":
info.inline = inlineNone
case "//go:linkname":
if len(parts) != 3 || parts[1] != f.Name() {
continue
}
// Only enable go:linkname when the package imports "unsafe".
// This is a slightly looser requirement than what gc uses: gc
// requires the file to import "unsafe", not the package as a
// whole.
if hasUnsafeImport(f.Pkg.Pkg) {
info.linkName = parts[2]
}
case "//go:section":
// Only enable go:section when the package imports "unsafe".
// go:section also implies go:noinline since inlining could
// move the code to a different section than that requested.
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
info.section = parts[1]
info.inline = inlineNone
case "//go:linkname":
if len(parts) != 3 || parts[1] != f.Name() {
continue
}
// Only enable go:linkname when the package imports "unsafe".
// This is a slightly looser requirement than what gc uses: gc
// requires the file to import "unsafe", not the package as a
// whole.
if hasUnsafeImport(f.Pkg.Pkg) {
info.linkName = parts[2]
}
case "//go:section":
// Only enable go:section when the package imports "unsafe".
// go:section also implies go:noinline since inlining could
// move the code to a different section than that requested.
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
info.section = parts[1]
info.inline = inlineNone
}
case "//go:nobounds":
// Skip bounds checking in this function. Useful for some
// runtime functions.
// This is somewhat dangerous and thus only imported in packages
// that import unsafe.
if hasUnsafeImport(f.Pkg.Pkg) {
info.nobounds = true
}
case "//go:variadic":
// The //go:variadic pragma is emitted by the CGo preprocessing
// pass for C variadic functions. This includes both explicit
// (with ...) and implicit (no parameters in signature)
// functions.
if strings.HasPrefix(f.Name(), "C.") {
// This prefix cannot naturally be created, it must have
// been created as a result of CGo preprocessing.
info.variadic = true
}
}
case "//go:nobounds":
// Skip bounds checking in this function. Useful for some
// runtime functions.
// This is somewhat dangerous and thus only imported in packages
// that import unsafe.
if hasUnsafeImport(f.Pkg.Pkg) {
info.nobounds = true
}
case "//go:variadic":
// The //go:variadic pragma is emitted by the CGo preprocessing
// pass for C variadic functions. This includes both explicit
// (with ...) and implicit (no parameters in signature)
// functions.
if strings.HasPrefix(f.Name(), "C.") {
// This prefix cannot naturally be created, it must have
// been created as a result of CGo preprocessing.
info.variadic = true
}
}
}
}
// Check whether this function cannot be used in //go:wasmimport. It will add an
// error if this is the case.
// Check whether this function can be used in //go:wasmimport or
// //go:wasmexport. It will add an error if this is not the case.
//
// The list of allowed types is based on this proposal:
// https://github.com/golang/go/issues/59149
func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string) {
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" {
// The runtime is a special case. Allow all kinds of parameters
// (importantly, including pointers).
return
}
if f.Blocks != nil {
// Defined functions cannot be exported.
c.addError(f.Pos(), "can only use //go:wasmimport on declarations")
return
}
if f.Signature.Results().Len() > 1 {
c.addError(f.Signature.Results().At(1).Pos(), fmt.Sprintf("%s: too many return values", pragma))
} else if f.Signature.Results().Len() == 1 {
result := f.Signature.Results().At(0)
if !isValidWasmType(result.Type(), siteResult) {
if !c.isValidWasmType(result.Type(), siteResult) {
c.addError(result.Pos(), fmt.Sprintf("%s: unsupported result type %s", pragma, result.Type().String()))
}
}
for _, param := range f.Params {
// Check whether the type is allowed.
// Only a very limited number of types can be mapped to WebAssembly.
if !isValidWasmType(param.Type(), siteParam) {
if !c.isValidWasmType(param.Type(), siteParam) {
c.addError(param.Pos(), fmt.Sprintf("%s: unsupported parameter type %s", pragma, param.Type().String()))
}
}
@@ -382,13 +443,15 @@ func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
//
// This previously reflected the additional restrictions documented here:
// https://github.com/golang/go/issues/59149
func isValidWasmType(typ types.Type, site wasmSite) bool {
func (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {
switch typ := typ.Underlying().(type) {
case *types.Basic:
switch typ.Kind() {
case types.Bool:
return true
case types.Int, types.Uint, types.Int8, types.Uint8, types.Int16, types.Uint16, types.Int32, types.Uint32, types.Int64, types.Uint64:
case types.Int8, types.Uint8, types.Int16, types.Uint16:
return site == siteIndirect
case types.Int32, types.Uint32, types.Int64, types.Uint64:
return true
case types.Float32, types.Float64:
return true
@@ -399,19 +462,35 @@ func isValidWasmType(typ types.Type, site wasmSite) bool {
return site == siteParam || site == siteIndirect
}
case *types.Array:
return site == siteIndirect && isValidWasmType(typ.Elem(), siteIndirect)
return site == siteIndirect && c.isValidWasmType(typ.Elem(), siteIndirect)
case *types.Struct:
if site != siteIndirect {
return false
}
// Structs with no fields do not need structs.HostLayout
if typ.NumFields() == 0 {
return true
}
hasHostLayout := true // default to true before detecting Go version
// (*types.Package).GoVersion added in go1.21
if gv, ok := any(c.pkg).(interface{ GoVersion() string }); ok {
if goenv.Compare(gv.GoVersion(), "go1.23") >= 0 {
hasHostLayout = false // package structs added in go1.23
}
}
for i := 0; i < typ.NumFields(); i++ {
if !isValidWasmType(typ.Field(i).Type(), siteIndirect) {
ftyp := typ.Field(i).Type()
if ftyp.String() == "structs.HostLayout" {
hasHostLayout = true
continue
}
if !c.isValidWasmType(ftyp, siteIndirect) {
return false
}
}
return true
return hasHostLayout
case *types.Pointer:
return isValidWasmType(typ.Elem(), siteIndirect)
return c.isValidWasmType(typ.Elem(), siteIndirect)
}
return false
}
+37 -7
View File
@@ -1,6 +1,9 @@
package main
import "unsafe"
import (
"structs"
"unsafe"
)
//go:wasmimport modulename empty
func empty()
@@ -14,31 +17,37 @@ func implementation() {
type Uint uint32
type S struct {
_ structs.HostLayout
a [4]uint32
b uintptr
c int
d float32
e float64
}
//go:wasmimport modulename validparam
func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint, f uintptr, g string, h *int32, i *S)
func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint, f uintptr, g string, h *int32, i *S, j *struct{}, k *[8]uint8)
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type [4]uint32
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type struct{a int}
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type chan struct{}
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type func()
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type uint
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type [8]int
//
//go:wasmimport modulename invalidparam
func invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func())
func invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func(), f int, g uint, h [8]int)
// ERROR: //go:wasmimport modulename invalidparam_no_hostlayout: unsupported parameter type *struct{int}
// ERROR: //go:wasmimport modulename invalidparam_no_hostlayout: unsupported parameter type *struct{string}
//
//go:wasmimport modulename invalidparam_no_hostlayout
func invalidparam_no_hostlayout(a *struct{ int }, b *struct{ string })
//go:wasmimport modulename validreturn_int32
func validreturn_int32() int32
//go:wasmimport modulename validreturn_int
func validreturn_int() int
//go:wasmimport modulename validreturn_ptr_int32
func validreturn_ptr_int32() *int32
@@ -48,6 +57,12 @@ func validreturn_ptr_string() *string
//go:wasmimport modulename validreturn_ptr_struct
func validreturn_ptr_struct() *S
//go:wasmimport modulename validreturn_ptr_struct
func validreturn_ptr_empty_struct() *struct{}
//go:wasmimport modulename validreturn_ptr_array
func validreturn_ptr_array() *[8]uint8
//go:wasmimport modulename validreturn_unsafe_pointer
func validreturn_unsafe_pointer() unsafe.Pointer
@@ -56,11 +71,26 @@ func validreturn_unsafe_pointer() unsafe.Pointer
//go:wasmimport modulename manyreturns
func manyreturns() (int32, int32)
// ERROR: //go:wasmimport modulename invalidreturn_int: unsupported result type int
//
//go:wasmimport modulename invalidreturn_int
func invalidreturn_int() int
// ERROR: //go:wasmimport modulename invalidreturn_int: unsupported result type uint
//
//go:wasmimport modulename invalidreturn_int
func invalidreturn_uint() uint
// ERROR: //go:wasmimport modulename invalidreturn_func: unsupported result type func()
//
//go:wasmimport modulename invalidreturn_func
func invalidreturn_func() func()
// ERROR: //go:wasmimport modulename invalidreturn_pointer_array_int: unsupported result type *[8]int
//
//go:wasmimport modulename invalidreturn_pointer_array_int
func invalidreturn_pointer_array_int() *[8]int
// ERROR: //go:wasmimport modulename invalidreturn_slice_byte: unsupported result type []byte
//
//go:wasmimport modulename invalidreturn_slice_byte
+16
View File
@@ -48,6 +48,22 @@ func inlineFunc() {
func noinlineFunc() {
}
type Int interface {
int8 | int16
}
// Same for generic functions (but the compiler may miss the pragma due to it
// being generic).
//
//go:noinline
func noinlineGenericFunc[T Int]() {
}
func useGeneric() {
// Make sure the generic function above is instantiated.
noinlineGenericFunc[int8]()
}
// This function should have the specified section.
//
//go:section .special_function_section
+13
View File
@@ -48,6 +48,19 @@ entry:
ret void
}
; Function Attrs: nounwind
define hidden void @main.useGeneric(ptr %context) unnamed_addr #2 {
entry:
call void @"main.noinlineGenericFunc[int8]"(ptr undef)
ret void
}
; Function Attrs: noinline nounwind
define linkonce_odr hidden void @"main.noinlineGenericFunc[int8]"(ptr %context) unnamed_addr #5 {
entry:
ret void
}
; Function Attrs: noinline nounwind
define hidden void @main.functionInSection(ptr %context) unnamed_addr #5 section ".special_function_section" {
entry:
+2
View File
@@ -24,6 +24,8 @@ func TestErrors(t *testing.T) {
{name: "cgo"},
{name: "compiler"},
{name: "interp"},
{name: "invalidmain"},
{name: "invalidname"},
{name: "linker-flashoverflow", target: "cortex-m-qemu"},
{name: "linker-ramoverflow", target: "cortex-m-qemu"},
{name: "linker-undefined", target: "darwin/arm64"},
Generated
+4 -4
View File
@@ -20,16 +20,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1703068421,
"narHash": "sha256-WSw5Faqlw75McIflnl5v7qVD/B3S2sLh+968bpOGrWA=",
"lastModified": 1728500571,
"narHash": "sha256-dOymOQ3AfNI4Z337yEwHGohrVQb4yPODCW9MDUyAc4w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d65bceaee0fb1e64363f7871bc43dc1c6ecad99f",
"rev": "d51c28603def282a24fa034bcb007e2bcb5b5dd0",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-23.11",
"ref": "nixos-24.05",
"type": "indirect"
}
},
+6 -6
View File
@@ -35,7 +35,7 @@
inputs = {
# Use a recent stable release, but fix the version to make it reproducible.
# This version should be updated from time to time.
nixpkgs.url = "nixpkgs/nixos-23.11";
nixpkgs.url = "nixpkgs/nixos-24.05";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
@@ -49,11 +49,11 @@
buildInputs = [
# These dependencies are required for building tinygo (go install).
go
llvmPackages_17.llvm
llvmPackages_17.libclang
llvmPackages_18.llvm
llvmPackages_18.libclang
# Additional dependencies needed at runtime, for building and/or
# flashing.
llvmPackages_17.lld
llvmPackages_18.lld
avrdude
binaryen
# Additional dependencies needed for on-chip debugging.
@@ -68,7 +68,7 @@
# Without setting these explicitly, Homebrew versions might be used
# or the default `ar` and `nm` tools might be used (which don't
# support wasi).
export CLANG="clang-17 -resource-dir ${llvmPackages_17.clang.cc.lib}/lib/clang/17"
export CLANG="clang-18 -resource-dir ${llvmPackages_18.clang.cc.lib}/lib/clang/18"
export LLVM_AR=llvm-ar
export LLVM_NM=llvm-nm
@@ -77,7 +77,7 @@
export MD5SUM=md5sum
# Ugly hack to make the Clang resources directory available.
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_17.clang.cc.lib}/lib/clang/17\" -tags=llvm17"
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_18.clang.cc.lib}/lib/clang/18\" -tags=llvm18"
'';
};
}
+1
View File
@@ -14,6 +14,7 @@ require (
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-tty v0.0.4
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
github.com/tetratelabs/wazero v1.6.0
go.bug.st/serial v1.6.0
golang.org/x/net v0.26.0
golang.org/x/sys v0.21.0
+2 -5
View File
@@ -12,7 +12,6 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
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/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
@@ -45,19 +44,18 @@ github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3px
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
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/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
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/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g=
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -76,6 +74,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8 h1:bLsZXRUBavt++CJlMN7sppNziqu3LyamESLhFJcpqFQ=
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+46 -9
View File
@@ -9,7 +9,7 @@ import (
// Version of TinyGo.
// Update this value before release of new version of software.
const version = "0.34.0-dev"
const version = "0.34.0"
var (
// This variable is set at build time using -ldflags parameters.
@@ -34,27 +34,64 @@ func GetGorootVersion() (major, minor int, err error) {
if err != nil {
return 0, 0, err
}
major, minor, _, err = Parse(s)
return major, minor, err
}
if s == "" || s[:2] != "go" {
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
// Parse parses the Go version (like "go1.3.2") in the parameter and return the
// major, minor, and patch version: 1, 3, and 2 in this example.
// If there is an error, (0, 0, 0) and an error will be returned.
func Parse(version string) (major, minor, patch int, err error) {
if version == "" || version[:2] != "go" {
return 0, 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
}
parts := strings.Split(s[2:], ".")
parts := strings.Split(version[2:], ".")
if len(parts) < 2 {
return 0, 0, errors.New("could not parse Go version: version has less than two parts")
return 0, 0, 0, errors.New("could not parse Go version: version has less than two parts")
}
// Ignore the errors, we don't really handle errors here anyway.
var trailing string
n, err := fmt.Sscanf(s, "go%d.%d%s", &major, &minor, &trailing)
if n == 2 && err == io.EOF {
n, err := fmt.Sscanf(version, "go%d.%d.%d%s", &major, &minor, &patch, &trailing)
if n == 2 {
n, err = fmt.Sscanf(version, "go%d.%d%s", &major, &minor, &trailing)
}
if n >= 2 && err == io.EOF {
// Means there were no trailing characters (i.e., not an alpha/beta)
err = nil
}
if err != nil {
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
return 0, 0, 0, fmt.Errorf("failed to parse version: %s", err)
}
return major, minor, patch, nil
}
// Compare compares two Go version strings.
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
// If either a or b is not a valid Go version, it is treated as "go0.0"
// and compared lexicographically.
// See [Parse] for more information.
func Compare(a, b string) int {
aMajor, aMinor, aPatch, _ := Parse(a)
bMajor, bMinor, bPatch, _ := Parse(b)
switch {
case aMajor < bMajor:
return -1
case aMajor > bMajor:
return +1
case aMinor < bMinor:
return -1
case aMinor > bMinor:
return +1
case aPatch < bPatch:
return -1
case aPatch > bPatch:
return +1
default:
return strings.Compare(a, b)
}
return
}
// GorootVersionString returns the version string as reported by the Go
+71
View File
@@ -0,0 +1,71 @@
package goenv
import "testing"
func TestParse(t *testing.T) {
tests := []struct {
v string
major int
minor int
patch int
wantErr bool
}{
{"", 0, 0, 0, true},
{"go", 0, 0, 0, true},
{"go1", 0, 0, 0, true},
{"go.0", 0, 0, 0, true},
{"go1.0", 1, 0, 0, false},
{"go1.1", 1, 1, 0, false},
{"go1.23", 1, 23, 0, false},
{"go1.23.5", 1, 23, 5, false},
{"go1.23.5-rc6", 1, 23, 5, false},
{"go2.0", 2, 0, 0, false},
{"go2.0.15", 2, 0, 15, false},
}
for _, tt := range tests {
t.Run(tt.v, func(t *testing.T) {
major, minor, patch, err := Parse(tt.v)
if err == nil && tt.wantErr {
t.Errorf("Parse(%q): expected err != nil", tt.v)
}
if err != nil && !tt.wantErr {
t.Errorf("Parse(%q): expected err == nil", tt.v)
}
if major != tt.major || minor != tt.minor || patch != tt.patch {
t.Errorf("Parse(%q): expected %d, %d, %d, nil; got %d, %d, %d, %v",
tt.v, tt.major, tt.minor, tt.patch, major, minor, patch, err)
}
})
}
}
func TestCompare(t *testing.T) {
tests := []struct {
a string
b string
want int
}{
{"", "", 0},
{"go0", "go0", 0},
{"go0", "go1", -1},
{"go1", "go0", 1},
{"go1", "go2", -1},
{"go2", "go1", 1},
{"go1.1", "go1.2", -1},
{"go1.2", "go1.1", 1},
{"go1.1.0", "go1.2.0", -1},
{"go1.2.0", "go1.1.0", 1},
{"go1.2.0", "go2.3.0", -1},
{"go1.23.2", "go1.23.10", -1},
{"go0.1.22", "go1.23.101", -1},
}
for _, tt := range tests {
t.Run(tt.a+" "+tt.b, func(t *testing.T) {
got := Compare(tt.a, tt.b)
if got != tt.want {
t.Errorf("Compare(%q, %q): expected %d; got %d",
tt.a, tt.b, tt.want, got)
}
})
}
}
+8 -1
View File
@@ -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
)
+25 -4
View File
@@ -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=
@@ -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=
+28 -24
View File
@@ -229,30 +229,34 @@ func needsSyscallPackage(buildTags []string) bool {
// means use the TinyGo version.
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
paths := map[string]bool{
"": true,
"crypto/": true,
"crypto/rand/": false,
"crypto/tls/": false,
"device/": false,
"examples/": false,
"internal/": true,
"internal/abi/": false,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/cm/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/task/": false,
"internal/wasi/": false,
"machine/": false,
"net/": true,
"net/http/": false,
"os/": true,
"reflect/": false,
"runtime/": false,
"sync/": true,
"testing/": true,
"unique/": false,
"": true,
"crypto/": true,
"crypto/rand/": false,
"crypto/tls/": false,
"crypto/x509/": true,
"crypto/x509/internal/": true,
"crypto/x509/internal/macos/": false,
"device/": false,
"examples/": false,
"internal/": true,
"internal/abi/": false,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/cm/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/gclayout": false,
"internal/task/": false,
"internal/wasi/": false,
"machine/": false,
"net/": true,
"net/http/": false,
"os/": true,
"reflect/": false,
"runtime/": false,
"sync/": true,
"testing/": true,
"unique/": false,
}
if goMinor >= 19 {
+15 -3
View File
@@ -418,8 +418,12 @@ func (p *Package) Check() error {
packageName := p.ImportPath
if p == p.program.MainPkg() {
if p.Name != "main" {
// Sanity check. Should not ever trigger.
panic("expected main package to have name 'main'")
return Errors{p, []error{
scanner.Error{
Pos: p.program.fset.Position(p.Files[0].Name.Pos()),
Msg: fmt.Sprintf("expected main package to have name \"main\", not %#v", p.Name),
},
}}
}
packageName = "main"
}
@@ -428,7 +432,15 @@ func (p *Package) Check() error {
if err, ok := err.(Errors); ok {
return err
}
return Errors{p, typeErrors}
if len(typeErrors) != 0 {
// Got type errors, so return them.
return Errors{p, typeErrors}
}
// This can happen in some weird cases.
// The only case I know is when compiling a Go 1.23 program, with a
// TinyGo version that supports Go 1.23 but is compiled using Go 1.22.
// So this should be pretty rare.
return Errors{p, []error{err}}
}
p.Pkg = typesPkg
+250 -85
View File
@@ -283,46 +283,6 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
// Tests are always run in the package directory.
cmd.Dir = result.MainDir
// wasmtime is the default emulator used for `-target=wasip1`. wasmtime
// is a WebAssembly runtime CLI with WASI enabled by default. However,
// only stdio are allowed by default. For example, while STDOUT routes
// to the host, other files don't. It also does not inherit environment
// variables from the host. Some tests read testdata files, often from
// outside the package directory. Other tests require temporary
// writeable directories. We allow this by adding wasmtime flags below.
if config.EmulatorName() == "wasmtime" {
// At this point, The current working directory is at the package
// directory. Ex. $GOROOT/src/compress/flate for compress/flate.
// buildAndRun has already added arguments for wasmtime, that allow
// read-access to files such as "testdata/huffman-zero.in".
//
// Ex. main(.wasm) --dir=. -- -test.v
// Below adds additional wasmtime flags in case a test reads files
// outside its directory, like "../testdata/e.txt". This allows any
// relative directory up to the module root, even if the test never
// reads any files.
//
// Ex. run --dir=.. --dir=../.. --dir=../../..
var dirs []string
switch config.Target.GOOS {
case "wasip1":
dirs = dirsToModuleRootRel(result.MainDir, result.ModuleRoot)
default:
dirs = dirsToModuleRootAbs(result.MainDir, result.ModuleRoot)
}
args := []string{"run"}
for _, d := range dirs {
args = append(args, "--dir="+d)
}
args = append(args, "--env=PWD="+cmd.Dir)
args = append(args, cmd.Args[1:]...)
cmd.Args = args
}
// Run the test.
start := time.Now()
err = cmd.Run()
@@ -848,12 +808,11 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
for _, v := range environmentVars {
emuArgs = append(emuArgs, "--env", v)
}
if len(cmdArgs) != 0 {
// Use of '--' argument no longer necessary as of Wasmtime v14:
// https://github.com/bytecodealliance/wasmtime/pull/6946
// args = append(args, "--")
args = append(args, cmdArgs...)
}
// Use of '--' argument no longer necessary as of Wasmtime v14:
// https://github.com/bytecodealliance/wasmtime/pull/6946
// args = append(args, "--")
args = append(args, cmdArgs...)
// Set this for nicer backtraces during tests, but don't override the user.
if _, ok := os.LookupEnv("WASMTIME_BACKTRACE_DETAILS"); !ok {
@@ -903,21 +862,36 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
name = emulator[0]
// wasmtime is a WebAssembly runtime CLI with WASI enabled by default.
// By default, only stdio is allowed. For example, while STDOUT routes
// to the host, other files don't. It also does not inherit environment
// variables from the host. Some tests read testdata files, often from
// outside the package directory. Other tests require temporary
// writeable directories. We allow this by adding wasmtime flags below.
if name == "wasmtime" {
// Wasmtime needs some special flags to pass environment variables
// and allow reading from the current directory.
switch config.Options.Target {
case "wasip1":
emuArgs = append(emuArgs, "--dir=.")
case "wasip2":
dir := result.MainDir
if isSingleFile {
cwd, _ := os.Getwd()
dir = cwd
// Below adds additional wasmtime flags in case a test reads files
// outside its directory, like "../testdata/e.txt". This allows any
// relative directory up to the module root, even if the test never
// reads any files.
if config.TestConfig.CompileTestBinary {
// Add relative dirs (../, ../..) up to module root (for wasip1)
dirs := dirsToModuleRootRel(result.MainDir, result.ModuleRoot)
// Add absolute dirs up to module root (for wasip2)
dirs = append(dirs, dirsToModuleRootAbs(result.MainDir, result.ModuleRoot)...)
for _, d := range dirs {
emuArgs = append(emuArgs, "--dir="+d)
}
emuArgs = append(emuArgs, "--dir="+dir)
emuArgs = append(emuArgs, "--env=PWD="+dir)
}
dir := result.MainDir
if isSingleFile {
dir, _ = os.Getwd()
}
emuArgs = append(emuArgs, "--dir=.")
emuArgs = append(emuArgs, "--dir="+dir)
emuArgs = append(emuArgs, "--env=PWD="+dir)
}
emuArgs = append(emuArgs, emulator[1:]...)
@@ -1256,36 +1230,169 @@ func getBMPPorts() (gdbPort, uartPort string, err error) {
}
}
func usage(command string) {
switch command {
default:
fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.")
fmt.Fprintln(os.Stderr, "version:", goenv.Version())
fmt.Fprintf(os.Stderr, "usage: %s <command> [arguments]\n", os.Args[0])
fmt.Fprintln(os.Stderr, "\ncommands:")
fmt.Fprintln(os.Stderr, " build: compile packages and dependencies")
fmt.Fprintln(os.Stderr, " run: compile and run immediately")
fmt.Fprintln(os.Stderr, " test: test packages")
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
fmt.Fprintln(os.Stderr, " monitor: open communication port")
fmt.Fprintln(os.Stderr, " ports: list available serial ports")
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
fmt.Fprintln(os.Stderr, " targets: list targets")
fmt.Fprintln(os.Stderr, " info: show info for specified target")
fmt.Fprintln(os.Stderr, " version: show version")
fmt.Fprintln(os.Stderr, " help: print this help text")
const (
usageBuild = `Build compiles the packages named by the import paths, along with their
dependencies, but it does not install the results. The output binary is
specified using the -o parameter. The generated file type depends on the
extension:
.o:
Create a relocatable object file. You can use this option if you
don't want to use the TinyGo build system or want to do other custom
things.
.ll:
Create textual LLVM IR, after optimization. This is mainly useful
for debugging.
.bc:
Create LLVM bitcode, after optimization. This may be useful for
debugging or for linking into other programs using LTO.
.hex:
Create an Intel HEX file to flash it to a microcontroller.
.bin:
Similar, but create a binary file.
.wasm:
Compile and link a WebAssembly file.
(all other) Compile and link the program into a regular executable. For
microcontrollers, it is common to use the .elf file extension to indicate a
linked ELF file is generated. For Linux, it is common to build binaries with no
extension at all.`
usageRun = `Run the program, either directly on the host or in an emulated environment
(depending on -target).`
usageFlash = `Flash the program to a microcontroller. Some common flags are described below.
-target={name}:
Specifies the type of microcontroller that is used. The name of the
microcontroller is given on the individual pages for each board type
listed under Microcontrollers
(https://tinygo.org/docs/reference/microcontrollers/).
Examples: "arduino-nano", "d1mini", "xiao".
-monitor:
Start the serial monitor (see below) immediately after
flashing. However, some microcontrollers need a split second
or two to configure the serial port after flashing, and
using the "-monitor" flag can fail because the serial
monitor starts too quickly. In that case, use the "tinygo
monitor" command explicitly.`
usageMonitor = `Start the serial monitor on the serial port that is connected to the
microcontroller. If there is only a single board attached to the host computer,
the default values for various options should be sufficient. In other
situations, particularly if you have multiple microcontrollers attached, some
parameters may need to be overridden using the following flags:
-port={port}:
If there are multiple microcontroller attached, an error
message will display a list of potential serial ports. The
appropriate port can be specified by this flag. On Linux,
the port will be something like /dev/ttyUSB0 or /dev/ttyACM1.
On MacOS, the port will look like /dev/cu.usbserial-1420. On
Windows, the port will be something like COM1 or COM31.
-baudrate={rate}:
The default baud rate is 115200. Boards using the AVR
processor (e.g. Arduino Nano, Arduino Mega 2560) use 9600
instead.
-target={name}:
If you have more than one microcontrollers attached, you can
sometimes just specify the target name and let tinygo
monitor figure out the port. Sometimes, this does not work
and you have to explicitly use the -port flag.
The serial monitor intercepts several control characters for its own use instead of sending them
to the microcontroller:
Control-C: terminates the tinygo monitor
Control-Z: suspends the tinygo monitor and drops back into shell
Control-\: terminates the tinygo monitor with a stack trace
Control-S: flow control, suspends output to the console
Control-Q: flow control, resumes output to the console
Control-@: thrown away by tinygo monitor
Note: If you are using os.Stdin on the microcontroller, you may find that a CR
character on the host computer (also known as Enter, ^M, or \r) is transmitted
to the microcontroller without conversion, so os.Stdin returns a \r character
instead of the expected \n (also known as ^J, NL, or LF) to indicate
end-of-line. You may be able to get around this problem by hitting Control-J in
tinygo monitor to transmit the \n end-of-line character.`
usageGdb = `Build the program, optionally flash it to a microcontroller if it is a remote
target, and drop into a GDB shell. From there you can set breakpoints, start the
program with "run" or "continue" ("run" for a local program, continue for
on-chip debugging), single-step, show a backtrace, break and resume the program
with Ctrl-C/"continue", etc. You may need to install extra tools (like openocd
and arm-none-eabi-gdb) to be able to do this. Also, you may need a dedicated
debugger to be able to debug certain boards if no debugger is integrated. Some
boards (like the BBC micro:bit and most professional evaluation boards) have an
integrated debugger.`
usageClean = `Clean the cache directory, normally stored in $HOME/.cache/tinygo. This is not
normally needed.`
usageHelp = `Print a short summary of the available commands, plus a list of command flags.`
usageVersion = `Print the version of the command and the version of the used $GOROOT.`
usageEnv = `Print a list of environment variables that affect TinyGo (as a shell script).
If one or more variable names are given as arguments, env prints the value of
each on a new line.`
usageDefault = `TinyGo is a Go compiler for small places.
version: %s
usage: %s <command> [arguments]
commands:
build: compile packages and dependencies
run: compile and run immediately
test: test packages
flash: compile and flash to the device
gdb: run/flash and immediately enter GDB
lldb: run/flash and immediately enter LLDB
monitor: open communication port
ports: list available serial ports
env: list environment variables used during build
list: run go list using the TinyGo root
clean: empty cache directory (%s)
targets: list targets
info: show info for specified target
version: show version
help: print this help text`
)
var (
commandHelp = map[string]string{
"build": usageBuild,
"run": usageRun,
"flash": usageFlash,
"monitor": usageMonitor,
"gdb": usageGdb,
"clean": usageClean,
"help": usageHelp,
"version": usageVersion,
"env": usageEnv,
}
)
func usage(command string) {
val, ok := commandHelp[command]
if !ok {
fmt.Fprintf(os.Stderr, usageDefault, goenv.Version(), os.Args[0], goenv.Get("GOCACHE"))
if flag.Parsed() {
fmt.Fprintln(os.Stderr, "\nflags:")
flag.PrintDefaults()
}
fmt.Fprintln(os.Stderr, "\nfor more details, see https://tinygo.org/docs/reference/usage/")
} else {
fmt.Fprintln(os.Stderr, val)
}
}
func handleCompilerError(err error) {
@@ -1330,19 +1437,20 @@ func (m globalValuesFlag) Set(value string) error {
// parseGoLinkFlag parses the -ldflags parameter. Its primary purpose right now
// is the -X flag, for setting the value of global string variables.
func parseGoLinkFlag(flagsString string) (map[string]map[string]string, error) {
func parseGoLinkFlag(flagsString string) (map[string]map[string]string, string, error) {
set := flag.NewFlagSet("link", flag.ExitOnError)
globalVarValues := make(globalValuesFlag)
set.Var(globalVarValues, "X", "Set the value of the string variable to the given value.")
extLDFlags := set.String("extldflags", "", "additional flags to pass to external linker")
flags, err := shlex.Split(flagsString)
if err != nil {
return nil, err
return nil, "", err
}
err = set.Parse(flags)
if err != nil {
return nil, err
return nil, "", err
}
return map[string]map[string]string(globalVarValues), nil
return map[string]map[string]string(globalVarValues), *extLDFlags, nil
}
// getListOfPackages returns a standard list of packages for a given list that might
@@ -1392,6 +1500,7 @@ func main() {
var tags buildutil.TagsFlag
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
target := flag.String("target", "", "chip/board name or JSON target specification file")
buildMode := flag.String("buildmode", "", "build mode to use (default, c-shared)")
var stackSize uint64
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
size, err := bytesize.Parse(s)
@@ -1461,6 +1570,7 @@ func main() {
// Early command processing, before commands are interpreted by the Go flag
// library.
handleChdirFlag()
switch command {
case "clang", "ld.lld", "wasm-ld":
err := builder.RunTool(command, os.Args[2:]...)
@@ -1473,7 +1583,7 @@ func main() {
}
flag.CommandLine.Parse(os.Args[2:])
globalVarValues, err := parseGoLinkFlag(*ldflags)
globalVarValues, extLDFlags, err := parseGoLinkFlag(*ldflags)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@@ -1499,6 +1609,7 @@ func main() {
GOARM: goenv.Get("GOARM"),
GOMIPS: goenv.Get("GOMIPS"),
Target: *target,
BuildMode: *buildMode,
StackSize: stackSize,
Opt: *opt,
GC: *gc,
@@ -1528,6 +1639,7 @@ func main() {
Timeout: *timeout,
WITPackage: witPackage,
WITWorld: witWorld,
ExtLDFlags: extLDFlags,
}
if *printCommands {
options.PrintCommands = printCommand
@@ -1946,3 +2058,56 @@ type outputEntry struct {
stderr bool
data []byte
}
// handleChdirFlag handles the -C flag before doing anything else.
// The -C flag must be the first flag on the command line, to make it easy to find
// even with commands that have custom flag parsing.
// handleChdirFlag handles the flag by chdir'ing to the directory
// and then removing that flag from the command line entirely.
//
// We have to handle the -C flag this way for two reasons:
//
// 1. Toolchain selection needs to be in the right directory to look for go.mod and go.work.
//
// 2. A toolchain switch later on reinvokes the new go command with the same arguments.
// The parent toolchain has already done the chdir; the child must not try to do it again.
func handleChdirFlag() {
used := 2 // b.c. command at os.Args[1]
if used >= len(os.Args) {
return
}
var dir string
switch a := os.Args[used]; {
default:
return
case a == "-C", a == "--C":
if used+1 >= len(os.Args) {
return
}
dir = os.Args[used+1]
os.Args = slicesDelete(os.Args, used, used+2)
case strings.HasPrefix(a, "-C="), strings.HasPrefix(a, "--C="):
_, dir, _ = strings.Cut(a, "=")
os.Args = slicesDelete(os.Args, used, used+1)
}
if err := os.Chdir(dir); err != nil {
fmt.Fprintln(os.Stderr, "cannot chdir:", err)
os.Exit(1)
}
}
// go1.19 compatibility: lacks slices package
func slicesDelete[S ~[]E, E any](s S, i, j int) S {
_ = s[i:j:len(s)] // bounds check
if i == j {
return s
}
return append(s[:i], s[j:]...)
}
+279 -21
View File
@@ -6,6 +6,7 @@ package main
import (
"bufio"
"bytes"
"context"
"errors"
"flag"
"io"
@@ -21,6 +22,9 @@ import (
"time"
"github.com/aykevl/go-wasm"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/tinygo-org/tinygo/builder"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/diagnostics"
@@ -75,6 +79,7 @@ func TestBuild(t *testing.T) {
"oldgo/",
"print.go",
"reflect.go",
"signal.go",
"slice.go",
"sort.go",
"stdlib.go",
@@ -213,6 +218,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
// isWebAssembly := strings.HasPrefix(spec.Triple, "wasm")
isWASI := strings.HasPrefix(options.Target, "wasi")
isWebAssembly := isWASI || strings.HasPrefix(options.Target, "wasm") || (options.Target == "" && strings.HasPrefix(options.GOARCH, "wasm"))
isBaremetal := options.Target == "simavr" || options.Target == "cortex-m-qemu" || options.Target == "riscv-qemu"
for _, name := range tests {
if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") {
@@ -277,6 +283,13 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
continue
}
}
if isWebAssembly || isBaremetal || options.GOOS == "windows" {
switch name {
case "signal.go":
// Signals only work on POSIX-like systems.
continue
}
}
name := name // redefine to avoid race condition
t.Run(name, func(t *testing.T) {
@@ -392,17 +405,13 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
// of the path.
path := TESTDATA + "/" + name
// Get the expected output for this test.
txtpath := path[:len(path)-3] + ".txt"
expectedOutputPath := path[:len(path)-3] + ".txt"
pkgName := "./" + path
if path[len(path)-1] == '/' {
txtpath = path + "out.txt"
expectedOutputPath = path + "out.txt"
options.Directory = path
pkgName = "."
}
expected, err := os.ReadFile(txtpath)
if err != nil {
t.Fatal("could not read expected output file:", err)
}
config, err := builder.NewConfig(&options)
if err != nil {
@@ -424,10 +433,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
return
}
// putchar() prints CRLF, convert it to LF.
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows
actual := stdout.Bytes()
if config.EmulatorName() == "simavr" {
// Strip simavr log formatting.
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
@@ -442,17 +448,12 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
}
// Check whether the command ran successfully.
fail := false
if err != nil {
t.Log("failed to run:", err)
fail = true
} else if !bytes.Equal(expected, actual) {
t.Logf("output did not match (expected %d bytes, got %d bytes):", len(expected), len(actual))
t.Logf(string(Diff("expected", expected, "actual", actual)))
fail = true
t.Error("failed to run:", err)
}
checkOutput(t, expectedOutputPath, actual)
if fail {
if t.Failed() {
r := bufio.NewReader(bytes.NewReader(actual))
for {
line, err := r.ReadString('\n')
@@ -470,20 +471,21 @@ func TestWebAssembly(t *testing.T) {
t.Parallel()
type testCase struct {
name string
target string
panicStrategy string
imports []string
}
for _, tc := range []testCase{
// Test whether there really are no imports when using -panic=trap. This
// tests the bugfix for https://github.com/tinygo-org/tinygo/issues/4161.
{name: "panic-default", imports: []string{"wasi_snapshot_preview1.fd_write"}},
{name: "panic-trap", panicStrategy: "trap", imports: []string{}},
{name: "panic-default", target: "wasip1", imports: []string{"wasi_snapshot_preview1.fd_write", "wasi_snapshot_preview1.random_get"}},
{name: "panic-trap", target: "wasm-unknown", panicStrategy: "trap", imports: []string{}},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
tmpdir := t.TempDir()
options := optionsFromTarget("wasi", sema)
options := optionsFromTarget(tc.target, sema)
options.PanicStrategy = tc.panicStrategy
config, err := builder.NewConfig(&options)
if err != nil {
@@ -523,6 +525,262 @@ func TestWebAssembly(t *testing.T) {
}
}
func TestWasmExport(t *testing.T) {
t.Parallel()
type testCase struct {
name string
target string
buildMode string
scheduler string
file string
noOutput bool
command bool // call _start (command mode) instead of _initialize
}
tests := []testCase{
// "command mode" WASI
{
name: "WASIp1-command",
target: "wasip1",
command: true,
},
// "reactor mode" WASI (with -buildmode=c-shared)
{
name: "WASIp1-reactor",
target: "wasip1",
buildMode: "c-shared",
},
// Make sure reactor mode also works without a scheduler.
{
name: "WASIp1-reactor-noscheduler",
target: "wasip1",
buildMode: "c-shared",
scheduler: "none",
file: "wasmexport-noscheduler.go",
},
// Test -target=wasm-unknown with the default build mode (which is
// c-shared).
{
name: "wasm-unknown-reactor",
target: "wasm-unknown",
file: "wasmexport-noscheduler.go",
noOutput: true, // wasm-unknown cannot produce output
},
// Test -target=wasm-unknown with -buildmode=default, which makes it run
// in command mode.
{
name: "wasm-unknown-command",
target: "wasm-unknown",
buildMode: "default",
file: "wasmexport-noscheduler.go",
noOutput: true, // wasm-unknown cannot produce output
command: true,
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
// Build the wasm binary.
tmpdir := t.TempDir()
options := optionsFromTarget(tc.target, sema)
options.BuildMode = tc.buildMode
options.Scheduler = tc.scheduler
buildConfig, err := builder.NewConfig(&options)
if err != nil {
t.Fatal(err)
}
filename := "wasmexport.go"
if tc.file != "" {
filename = tc.file
}
result, err := builder.Build("testdata/"+filename, ".wasm", tmpdir, buildConfig)
if err != nil {
t.Fatal("failed to build binary:", err)
}
// Read the wasm binary back into memory.
data, err := os.ReadFile(result.Binary)
if err != nil {
t.Fatal("could not read wasm binary: ", err)
}
// Set up the wazero runtime.
output := &bytes.Buffer{}
ctx := context.Background()
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter())
defer r.Close(ctx)
config := wazero.NewModuleConfig().
WithStdout(output).WithStderr(output).
WithStartFunctions()
// Prepare for testing.
var mod api.Module
mustCall := func(results []uint64, err error) []uint64 {
if err != nil {
t.Error("failed to run function:", err)
}
return results
}
checkResult := func(name string, results []uint64, expected []uint64) {
if len(results) != len(expected) {
t.Errorf("%s: expected %v but got %v", name, expected, results)
}
for i, result := range results {
if result != expected[i] {
t.Errorf("%s: expected %v but got %v", name, expected, results)
break
}
}
}
runTests := func() {
// Test an exported function without params or return value.
checkResult("hello()", mustCall(mod.ExportedFunction("hello").Call(ctx)), nil)
// Test that we can call an exported function more than once.
checkResult("add(3, 5)", mustCall(mod.ExportedFunction("add").Call(ctx, 3, 5)), []uint64{8})
checkResult("add(7, 9)", mustCall(mod.ExportedFunction("add").Call(ctx, 7, 9)), []uint64{16})
checkResult("add(6, 1)", mustCall(mod.ExportedFunction("add").Call(ctx, 6, 1)), []uint64{7})
// Test that imported functions can call exported functions
// again.
checkResult("reentrantCall(2, 3)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 2, 3)), []uint64{5})
checkResult("reentrantCall(1, 8)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 1, 8)), []uint64{9})
}
// Add wasip1 module.
wasi_snapshot_preview1.MustInstantiate(ctx, r)
// Add custom "tester" module.
callOutside := func(a, b int32) int32 {
results, err := mod.ExportedFunction("add").Call(ctx, uint64(a), uint64(b))
if err != nil {
t.Error("could not call exported add function:", err)
}
return int32(results[0])
}
callTestMain := func() {
runTests()
}
builder := r.NewHostModuleBuilder("tester")
builder.NewFunctionBuilder().WithFunc(callOutside).Export("callOutside")
builder.NewFunctionBuilder().WithFunc(callTestMain).Export("callTestMain")
_, err = builder.Instantiate(ctx)
if err != nil {
t.Fatal(err)
}
// Parse and instantiate the wasm.
mod, err = r.InstantiateWithConfig(ctx, data, config)
if err != nil {
t.Fatal("could not instantiate wasm module:", err)
}
// Initialize the module and run the tests.
if tc.command {
// Call _start (the entry point), which calls
// tester.callTestMain, which then runs all the tests.
mustCall(mod.ExportedFunction("_start").Call(ctx))
} else {
// Run the _initialize call, because this is reactor mode wasm.
mustCall(mod.ExportedFunction("_initialize").Call(ctx))
runTests()
}
// Check that the output matches the expected output.
// (Skip this for wasm-unknown because it can't produce output).
if !tc.noOutput {
checkOutput(t, "testdata/wasmexport.txt", output.Bytes())
}
})
}
}
// Test js.FuncOf (for syscall/js).
// This test might be extended in the future to cover more cases in syscall/js.
func TestWasmFuncOf(t *testing.T) {
// Build the wasm binary.
tmpdir := t.TempDir()
options := optionsFromTarget("wasm", sema)
buildConfig, err := builder.NewConfig(&options)
if err != nil {
t.Fatal(err)
}
result, err := builder.Build("testdata/wasmfunc.go", ".wasm", tmpdir, buildConfig)
if err != nil {
t.Fatal("failed to build binary:", err)
}
// Test the resulting binary using NodeJS.
output := &bytes.Buffer{}
cmd := exec.Command("node", "testdata/wasmfunc.js", result.Binary, buildConfig.BuildMode())
cmd.Stdout = output
cmd.Stderr = output
err = cmd.Run()
if err != nil {
t.Error("failed to run node:", err)
}
checkOutput(t, "testdata/wasmfunc.txt", output.Bytes())
}
// Test //go:wasmexport in JavaScript (using NodeJS).
func TestWasmExportJS(t *testing.T) {
type testCase struct {
name string
buildMode string
}
tests := []testCase{
{name: "default"},
{name: "c-shared", buildMode: "c-shared"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// Build the wasm binary.
tmpdir := t.TempDir()
options := optionsFromTarget("wasm", sema)
options.BuildMode = tc.buildMode
buildConfig, err := builder.NewConfig(&options)
if err != nil {
t.Fatal(err)
}
result, err := builder.Build("testdata/wasmexport-noscheduler.go", ".wasm", tmpdir, buildConfig)
if err != nil {
t.Fatal("failed to build binary:", err)
}
// Test the resulting binary using NodeJS.
output := &bytes.Buffer{}
cmd := exec.Command("node", "testdata/wasmexport.js", result.Binary, buildConfig.BuildMode())
cmd.Stdout = output
cmd.Stderr = output
err = cmd.Run()
if err != nil {
t.Error("failed to run node:", err)
}
checkOutput(t, "testdata/wasmexport.txt", output.Bytes())
})
}
}
// Check whether the output of a test equals the expected output.
func checkOutput(t *testing.T, filename string, actual []byte) {
expectedOutput, err := os.ReadFile(filename)
if err != nil {
t.Fatal("could not read output file:", err)
}
expectedOutput = bytes.ReplaceAll(expectedOutput, []byte("\r\n"), []byte("\n"))
actual = bytes.ReplaceAll(actual, []byte("\r\n"), []byte("\n"))
if !bytes.Equal(actual, expectedOutput) {
t.Errorf("output did not match (expected %d bytes, got %d bytes):", len(expectedOutput), len(actual))
t.Error(string(Diff("expected", expectedOutput, "actual", actual)))
}
}
func TestTest(t *testing.T) {
t.Parallel()
+185
View File
@@ -0,0 +1,185 @@
package macos
import (
"errors"
"time"
)
// Exported symbols copied from Big Go, but stripped of functionality.
// Allows building of crypto/x509 on macOS.
const (
ErrSecCertificateExpired = -67818
ErrSecHostNameMismatch = -67602
ErrSecNotTrusted = -67843
)
var ErrNoTrustSettings = errors.New("no trust settings found")
var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO
var SecPolicyOid = StringToCFString("SecPolicyOid")
var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy")
var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString")
var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult")
func CFArrayAppendValue(array CFRef, val CFRef) {}
func CFArrayGetCount(array CFRef) int {
return 0
}
func CFDataGetBytePtr(data CFRef) uintptr {
return 0
}
func CFDataGetLength(data CFRef) int {
return 0
}
func CFDataToSlice(data CFRef) []byte {
return nil
}
func CFEqual(a, b CFRef) bool {
return false
}
func CFErrorGetCode(errRef CFRef) int {
return 0
}
func CFNumberGetValue(num CFRef) (int32, error) {
return 0, errors.New("not implemented")
}
func CFRelease(ref CFRef) {}
func CFStringToString(ref CFRef) string {
return ""
}
func ReleaseCFArray(array CFRef) {}
func SecCertificateCopyData(cert CFRef) ([]byte, error) {
return nil, errors.New("not implemented")
}
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
return 0, errors.New("not implemented")
}
func SecTrustGetCertificateCount(trustObj CFRef) int {
return 0
}
func SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) {
return 0, 0, errors.New("not implemented")
}
func SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error {
return errors.New("not implemented")
}
type CFRef uintptr
func BytesToCFData(b []byte) CFRef {
return 0
}
func CFArrayCreateMutable() CFRef {
return 0
}
func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
return 0
}
func CFDateCreate(seconds float64) CFRef {
return 0
}
func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
return 0, false
}
func CFErrorCopyDescription(errRef CFRef) CFRef {
return 0
}
func CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecCertificateCreateWithData(b []byte) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecPolicyCreateSSL(name string) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustEvaluate(trustObj CFRef) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) (CFRef, error) {
return 0, errors.New("not implemented")
}
func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
return 0, errors.New("not implemented")
}
func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
return 0, errors.New("not implemented")
}
func TimeToCFDateRef(t time.Time) CFRef {
return 0
}
type CFString CFRef
func StringToCFString(s string) CFString {
return 0
}
type OSStatus struct {
// Has unexported fields.
}
func (s OSStatus) Error() string
type SecTrustResultType int32
const (
SecTrustResultInvalid SecTrustResultType = iota
SecTrustResultProceed
SecTrustResultConfirm // deprecated
SecTrustResultDeny
SecTrustResultUnspecified
SecTrustResultRecoverableTrustFailure
SecTrustResultFatalTrustFailure
SecTrustResultOtherError
)
type SecTrustSettingsDomain int32
const (
SecTrustSettingsDomainUser SecTrustSettingsDomain = iota
SecTrustSettingsDomainAdmin
SecTrustSettingsDomainSystem
)
type SecTrustSettingsResult int32
const (
SecTrustSettingsResultInvalid SecTrustSettingsResult = iota
SecTrustSettingsResultTrustRoot
SecTrustSettingsResultTrustAsRoot
SecTrustSettingsResultDeny
SecTrustSettingsResultUnspecified
)
+5
View File
@@ -30,3 +30,8 @@ func (littleEndian) AppendUint16(b []byte, v uint16) []byte {
func (littleEndian) Uint32(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func (littleEndian) Uint64(b []byte) uint64 {
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
+28 -4
View File
@@ -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) {
@@ -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].
@@ -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 {
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].
//
+11
View File
@@ -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
View File
@@ -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
+20 -8
View File
@@ -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),
},
}
}
@@ -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.
@@ -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
}
+17 -2
View File
@@ -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.
@@ -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,
},
@@ -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
}
@@ -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
}
+17 -5
View File
@@ -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
@@ -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
@@ -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
+15
View File
@@ -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
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
+15 -3
View File
@@ -12,7 +12,18 @@ type Discriminant interface {
// Variant represents a loosely-typed Component Model variant.
// Shape and Align must be non-zero sized types. To create a variant with no associated
// types, use an enum.
type Variant[Tag Discriminant, Shape, Align any] struct{ variant[Tag, Shape, Align] }
type Variant[Tag Discriminant, Shape, Align any] struct {
_ HostLayout
variant[Tag, Shape, Align]
}
// AnyVariant is a type constraint for generic functions that accept any [Variant] type.
type AnyVariant[Tag Discriminant, Shape, Align any] interface {
~struct {
_ HostLayout
variant[Tag, Shape, Align]
}
}
// NewVariant returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,
// aligned to type Align, with a value of type T.
@@ -26,7 +37,7 @@ func NewVariant[Tag Discriminant, Shape, Align any, T any](tag Tag, data T) Vari
// New returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,
// aligned to type Align, with a value of type T.
func New[V ~struct{ variant[Tag, Shape, Align] }, Tag Discriminant, Shape, Align any, T any](tag Tag, data T) V {
func New[V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any, T any](tag Tag, data T) V {
validateVariant[Tag, Shape, Align, T]()
var v variant[Tag, Shape, Align]
v.tag = tag
@@ -35,7 +46,7 @@ func New[V ~struct{ variant[Tag, Shape, Align] }, Tag Discriminant, Shape, Align
}
// Case returns a non-nil *T if the [Variant] case is equal to tag, otherwise it returns nil.
func Case[T any, V ~struct{ variant[Tag, Shape, Align] }, Tag Discriminant, Shape, Align any](v *V, tag Tag) *T {
func Case[T any, V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any](v *V, tag Tag) *T {
validateVariant[Tag, Shape, Align, T]()
v2 := (*variant[Tag, Shape, Align])(unsafe.Pointer(v))
if v2.tag == tag {
@@ -47,6 +58,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
+33
View File
@@ -0,0 +1,33 @@
package gclayout
import "unsafe"
// Internal constants for gc layout
// See runtime/gc_precise.go
var (
NoPtrs unsafe.Pointer
Pointer unsafe.Pointer
String unsafe.Pointer
Slice unsafe.Pointer
)
func init() {
var sizeBits uintptr
switch unsafe.Sizeof(uintptr(0)) {
case 8:
sizeBits = 6
case 4:
sizeBits = 5
case 2:
sizeBits = 4
}
var sizeShift = sizeBits + 1
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
}
+3
View File
@@ -30,3 +30,6 @@ type Task struct {
// the given function and falls back to the default stack size. It is replaced
// with a load from a special section just before codegen.
func getGoroutineStackSize(fn uintptr) uintptr
//go:linkname runtime_alloc runtime.alloc
func runtime_alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
+19 -11
View File
@@ -35,11 +35,16 @@ type state struct {
type stackState struct {
// asyncify is the stack pointer of the asyncify stack.
// This starts from the bottom and grows upwards.
asyncifysp uintptr
asyncifysp unsafe.Pointer
// asyncify is stack pointer of the C stack.
// This starts from the top and grows downwards.
csp uintptr
csp unsafe.Pointer
// Pointer to the first (lowest address) of the stack. It must never be
// overwritten. It can be checked from time to time to see whether a stack
// overflow happened in the past.
canaryPtr *uintptr
}
// start creates and starts a new goroutine with the given function and arguments.
@@ -63,12 +68,18 @@ func (s *state) initialize(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
s.args = args
// Create a stack.
stack := make([]uintptr, stackSize/unsafe.Sizeof(uintptr(0)))
stack := runtime_alloc(stackSize, nil)
// Set up the stack canary, a random number that should be checked when
// switching from the task back to the scheduler. The stack canary pointer
// points to the first word of the stack. If it has changed between now and
// the next stack switch, there was a stack overflow.
s.canaryPtr = (*uintptr)(stack)
*s.canaryPtr = stackCanary
// Calculate stack base addresses.
s.asyncifysp = uintptr(unsafe.Pointer(&stack[0]))
s.csp = uintptr(unsafe.Pointer(&stack[0])) + uintptr(len(stack))*unsafe.Sizeof(uintptr(0))
stack[0] = stackCanary
s.asyncifysp = unsafe.Add(stack, unsafe.Sizeof(uintptr(0)))
s.csp = unsafe.Add(stack, stackSize)
}
//go:linkname runqueuePushBack runtime.runqueuePushBack
@@ -85,14 +96,11 @@ func Current() *Task {
// Pause suspends the current task and returns to the scheduler.
// This function may only be called when running on a goroutine stack, not when running on the system stack.
func Pause() {
// This is mildly unsafe but this is also the only place we can do this.
if *(*uintptr)(unsafe.Pointer(currentTask.state.asyncifysp)) != stackCanary {
if *currentTask.state.canaryPtr != stackCanary {
runtimePanic("stack overflow")
}
currentTask.state.unwind()
*(*uintptr)(unsafe.Pointer(currentTask.state.asyncifysp)) = stackCanary
}
//export tinygo_unwind
@@ -113,7 +121,7 @@ func (t *Task) Resume() {
}
currentTask = prevTask
t.gcData.swap()
if t.state.asyncifysp > t.state.csp {
if uintptr(t.state.asyncifysp) > uintptr(t.state.csp) {
runtimePanic("stack overflow")
}
}
-3
View File
@@ -104,9 +104,6 @@ var startTask [0]uint8
//go:linkname runqueuePushBack runtime.runqueuePushBack
func runqueuePushBack(*Task)
//go:linkname runtime_alloc runtime.alloc
func runtime_alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
// start creates and starts a new goroutine with the given function and arguments.
// The new goroutine is scheduled to run later.
func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package environment
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/environment@0.2.0 get-environment
//go:noescape
func wasmimport_GetEnvironment(result *cm.List[[2]string])
//go:wasmimport wasi:cli/environment@0.2.0 get-arguments
//go:noescape
func wasmimport_GetArguments(result *cm.List[string])
//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd
//go:noescape
func wasmimport_InitialCWD(result *cm.Option[string])
@@ -26,10 +26,6 @@ func GetEnvironment() (result cm.List[[2]string]) {
return
}
//go:wasmimport wasi:cli/environment@0.2.0 get-environment
//go:noescape
func wasmimport_GetEnvironment(result *cm.List[[2]string])
// GetArguments represents the imported function "get-arguments".
//
// Get the POSIX-style arguments to the program.
@@ -42,10 +38,6 @@ func GetArguments() (result cm.List[string]) {
return
}
//go:wasmimport wasi:cli/environment@0.2.0 get-arguments
//go:noescape
func wasmimport_GetArguments(result *cm.List[string])
// InitialCWD represents the imported function "initial-cwd".
//
// Return a path that programs should use as their initial current working
@@ -58,7 +50,3 @@ func InitialCWD() (result cm.Option[string]) {
wasmimport_InitialCWD(&result)
return
}
//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd
//go:noescape
func wasmimport_InitialCWD(result *cm.Option[string])
+9
View File
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package exit
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/exit@0.2.0 exit
//go:noescape
func wasmimport_Exit(status0 uint32)
@@ -19,7 +19,3 @@ func Exit(status cm.BoolResult) {
wasmimport_Exit((uint32)(status0))
return
}
//go:wasmimport wasi:cli/exit@0.2.0 exit
//go:noescape
func wasmimport_Exit(status0 uint32)
+17
View File
@@ -0,0 +1,17 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package run
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmexport wasi:cli/run@0.2.0#run
//export wasi:cli/run@0.2.0#run
func wasmexport_Run() (result0 uint32) {
result := Exports.Run()
result0 = cm.BoolToU32(result)
return
}
@@ -2,15 +2,3 @@
// Package run represents the exported interface "wasi:cli/run@0.2.0".
package run
import (
"internal/cm"
)
//go:wasmexport wasi:cli/run@0.2.0#run
//export wasi:cli/run@0.2.0#run
func wasmexport_Run() (result0 uint32) {
result := Exports.Run()
result0 = cm.BoolToU32(result)
return
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package stderr
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr
//go:noescape
func wasmimport_GetStderr() (result0 uint32)
@@ -8,17 +8,18 @@ import (
"internal/wasi/io/v0.2.0/streams"
)
// OutputStream represents the imported type alias "wasi:cli/stderr@0.2.0#output-stream".
//
// See [streams.OutputStream] for more information.
type OutputStream = streams.OutputStream
// GetStderr represents the imported function "get-stderr".
//
// get-stderr: func() -> output-stream
//
//go:nosplit
func GetStderr() (result streams.OutputStream) {
func GetStderr() (result OutputStream) {
result0 := wasmimport_GetStderr()
result = cm.Reinterpret[streams.OutputStream]((uint32)(result0))
result = cm.Reinterpret[OutputStream]((uint32)(result0))
return
}
//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr
//go:noescape
func wasmimport_GetStderr() (result0 uint32)
+9
View File
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package stdin
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin
//go:noescape
func wasmimport_GetStdin() (result0 uint32)
@@ -8,17 +8,18 @@ import (
"internal/wasi/io/v0.2.0/streams"
)
// InputStream represents the imported type alias "wasi:cli/stdin@0.2.0#input-stream".
//
// See [streams.InputStream] for more information.
type InputStream = streams.InputStream
// GetStdin represents the imported function "get-stdin".
//
// get-stdin: func() -> input-stream
//
//go:nosplit
func GetStdin() (result streams.InputStream) {
func GetStdin() (result InputStream) {
result0 := wasmimport_GetStdin()
result = cm.Reinterpret[streams.InputStream]((uint32)(result0))
result = cm.Reinterpret[InputStream]((uint32)(result0))
return
}
//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin
//go:noescape
func wasmimport_GetStdin() (result0 uint32)
+9
View File
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package stdout
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout
//go:noescape
func wasmimport_GetStdout() (result0 uint32)
@@ -8,17 +8,18 @@ import (
"internal/wasi/io/v0.2.0/streams"
)
// OutputStream represents the imported type alias "wasi:cli/stdout@0.2.0#output-stream".
//
// See [streams.OutputStream] for more information.
type OutputStream = streams.OutputStream
// GetStdout represents the imported function "get-stdout".
//
// get-stdout: func() -> output-stream
//
//go:nosplit
func GetStdout() (result streams.OutputStream) {
func GetStdout() (result OutputStream) {
result0 := wasmimport_GetStdout()
result = cm.Reinterpret[streams.OutputStream]((uint32)(result0))
result = cm.Reinterpret[OutputStream]((uint32)(result0))
return
}
//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout
//go:noescape
func wasmimport_GetStdout() (result0 uint32)
@@ -30,7 +30,3 @@ func (self TerminalInput) ResourceDrop() {
wasmimport_TerminalInputResourceDrop((uint32)(self0))
return
}
//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input
//go:noescape
func wasmimport_TerminalInputResourceDrop(self0 uint32)
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package terminalinput
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input
//go:noescape
func wasmimport_TerminalInputResourceDrop(self0 uint32)
@@ -30,7 +30,3 @@ func (self TerminalOutput) ResourceDrop() {
wasmimport_TerminalOutputResourceDrop((uint32)(self0))
return
}
//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output
//go:noescape
func wasmimport_TerminalOutputResourceDrop(self0 uint32)
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package terminaloutput
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output
//go:noescape
func wasmimport_TerminalOutputResourceDrop(self0 uint32)
@@ -11,6 +11,11 @@ import (
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
)
// TerminalOutput represents the imported type alias "wasi:cli/terminal-stderr@0.2.0#terminal-output".
//
// See [terminaloutput.TerminalOutput] for more information.
type TerminalOutput = terminaloutput.TerminalOutput
// GetTerminalStderr represents the imported function "get-terminal-stderr".
//
// If stderr is connected to a terminal, return a `terminal-output` handle
@@ -19,11 +24,7 @@ import (
// get-terminal-stderr: func() -> option<terminal-output>
//
//go:nosplit
func GetTerminalStderr() (result cm.Option[terminaloutput.TerminalOutput]) {
func GetTerminalStderr() (result cm.Option[TerminalOutput]) {
wasmimport_GetTerminalStderr(&result)
return
}
//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr
//go:noescape
func wasmimport_GetTerminalStderr(result *cm.Option[terminaloutput.TerminalOutput])
@@ -0,0 +1,13 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package terminalstderr
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr
//go:noescape
func wasmimport_GetTerminalStderr(result *cm.Option[TerminalOutput])
@@ -11,6 +11,11 @@ import (
terminalinput "internal/wasi/cli/v0.2.0/terminal-input"
)
// TerminalInput represents the imported type alias "wasi:cli/terminal-stdin@0.2.0#terminal-input".
//
// See [terminalinput.TerminalInput] for more information.
type TerminalInput = terminalinput.TerminalInput
// GetTerminalStdin represents the imported function "get-terminal-stdin".
//
// If stdin is connected to a terminal, return a `terminal-input` handle
@@ -19,11 +24,7 @@ import (
// get-terminal-stdin: func() -> option<terminal-input>
//
//go:nosplit
func GetTerminalStdin() (result cm.Option[terminalinput.TerminalInput]) {
func GetTerminalStdin() (result cm.Option[TerminalInput]) {
wasmimport_GetTerminalStdin(&result)
return
}
//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin
//go:noescape
func wasmimport_GetTerminalStdin(result *cm.Option[terminalinput.TerminalInput])
@@ -0,0 +1,13 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package terminalstdin
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin
//go:noescape
func wasmimport_GetTerminalStdin(result *cm.Option[TerminalInput])
@@ -11,6 +11,11 @@ import (
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
)
// TerminalOutput represents the imported type alias "wasi:cli/terminal-stdout@0.2.0#terminal-output".
//
// See [terminaloutput.TerminalOutput] for more information.
type TerminalOutput = terminaloutput.TerminalOutput
// GetTerminalStdout represents the imported function "get-terminal-stdout".
//
// If stdout is connected to a terminal, return a `terminal-output` handle
@@ -19,11 +24,7 @@ import (
// get-terminal-stdout: func() -> option<terminal-output>
//
//go:nosplit
func GetTerminalStdout() (result cm.Option[terminaloutput.TerminalOutput]) {
func GetTerminalStdout() (result cm.Option[TerminalOutput]) {
wasmimport_GetTerminalStdout(&result)
return
}
//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout
//go:noescape
func wasmimport_GetTerminalStdout(result *cm.Option[terminaloutput.TerminalOutput])
@@ -0,0 +1,13 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package terminalstdout
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout
//go:noescape
func wasmimport_GetTerminalStdout(result *cm.Option[TerminalOutput])
@@ -19,6 +19,11 @@ import (
"internal/wasi/io/v0.2.0/poll"
)
// Pollable represents the imported type alias "wasi:clocks/monotonic-clock@0.2.0#pollable".
//
// See [poll.Pollable] for more information.
type Pollable = poll.Pollable
// Instant represents the u64 "wasi:clocks/monotonic-clock@0.2.0#instant".
//
// An instant in time, in nanoseconds. An instant is relative to an
@@ -51,10 +56,6 @@ func Now() (result Instant) {
return
}
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now
//go:noescape
func wasmimport_Now() (result0 uint64)
// Resolution represents the imported function "resolution".
//
// Query the resolution of the clock. Returns the duration of time
@@ -69,10 +70,6 @@ func Resolution() (result Duration) {
return
}
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution
//go:noescape
func wasmimport_Resolution() (result0 uint64)
// SubscribeInstant represents the imported function "subscribe-instant".
//
// Create a `pollable` which will resolve once the specified instant
@@ -81,17 +78,13 @@ func wasmimport_Resolution() (result0 uint64)
// subscribe-instant: func(when: instant) -> pollable
//
//go:nosplit
func SubscribeInstant(when Instant) (result poll.Pollable) {
func SubscribeInstant(when Instant) (result Pollable) {
when0 := (uint64)(when)
result0 := wasmimport_SubscribeInstant((uint64)(when0))
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
result = cm.Reinterpret[Pollable]((uint32)(result0))
return
}
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant
//go:noescape
func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32)
// SubscribeDuration represents the imported function "subscribe-duration".
//
// Create a `pollable` which will resolve once the given duration has
@@ -101,13 +94,9 @@ func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32)
// subscribe-duration: func(when: duration) -> pollable
//
//go:nosplit
func SubscribeDuration(when Duration) (result poll.Pollable) {
func SubscribeDuration(when Duration) (result Pollable) {
when0 := (uint64)(when)
result0 := wasmimport_SubscribeDuration((uint64)(when0))
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
result = cm.Reinterpret[Pollable]((uint32)(result0))
return
}
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration
//go:noescape
func wasmimport_SubscribeDuration(when0 uint64) (result0 uint32)
@@ -0,0 +1,21 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package monotonicclock
// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0".
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now
//go:noescape
func wasmimport_Now() (result0 uint64)
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution
//go:noescape
func wasmimport_Resolution() (result0 uint64)
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant
//go:noescape
func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32)
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration
//go:noescape
func wasmimport_SubscribeDuration(when0 uint64) (result0 uint32)
@@ -18,6 +18,10 @@
// It is intended for reporting the current date and time for humans.
package wallclock
import (
"internal/cm"
)
// DateTime represents the record "wasi:clocks/wall-clock@0.2.0#datetime".
//
// A time and date in seconds plus nanoseconds.
@@ -27,6 +31,7 @@ package wallclock
// nanoseconds: u32,
// }
type DateTime struct {
_ cm.HostLayout
Seconds uint64
Nanoseconds uint32
}
@@ -55,10 +60,6 @@ func Now() (result DateTime) {
return
}
//go:wasmimport wasi:clocks/wall-clock@0.2.0 now
//go:noescape
func wasmimport_Now(result *DateTime)
// Resolution represents the imported function "resolution".
//
// Query the resolution of the clock.
@@ -72,7 +73,3 @@ func Resolution() (result DateTime) {
wasmimport_Resolution(&result)
return
}
//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution
//go:noescape
func wasmimport_Resolution(result *DateTime)
@@ -0,0 +1,13 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package wallclock
// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0".
//go:wasmimport wasi:clocks/wall-clock@0.2.0 now
//go:noescape
func wasmimport_Now(result *DateTime)
//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution
//go:noescape
func wasmimport_Resolution(result *DateTime)
@@ -0,0 +1,13 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package preopens
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0".
//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories
//go:noescape
func wasmimport_GetDirectories(result *cm.List[cm.Tuple[Descriptor, string]])
@@ -8,6 +8,11 @@ import (
"internal/wasi/filesystem/v0.2.0/types"
)
// Descriptor represents the imported type alias "wasi:filesystem/preopens@0.2.0#descriptor".
//
// See [types.Descriptor] for more information.
type Descriptor = types.Descriptor
// GetDirectories represents the imported function "get-directories".
//
// Return the set of preopened directories, and their path.
@@ -15,11 +20,7 @@ import (
// get-directories: func() -> list<tuple<descriptor, string>>
//
//go:nosplit
func GetDirectories() (result cm.List[cm.Tuple[types.Descriptor, string]]) {
func GetDirectories() (result cm.List[cm.Tuple[Descriptor, string]]) {
wasmimport_GetDirectories(&result)
return
}
//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories
//go:noescape
func wasmimport_GetDirectories(result *cm.List[cm.Tuple[types.Descriptor, string]])
@@ -8,18 +8,15 @@ import (
"unsafe"
)
// DateTimeShape is used for storage in variant or result types.
type DateTimeShape struct {
shape [unsafe.Sizeof(wallclock.DateTime{})]byte
}
// MetadataHashValueShape is used for storage in variant or result types.
type MetadataHashValueShape struct {
_ cm.HostLayout
shape [unsafe.Sizeof(MetadataHashValue{})]byte
}
// TupleListU8BoolShape is used for storage in variant or result types.
type TupleListU8BoolShape struct {
_ cm.HostLayout
shape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte
}
@@ -42,10 +39,12 @@ func lower_NewTimestamp(v NewTimestamp) (f0 uint32, f1 uint64, f2 uint32) {
// DescriptorStatShape is used for storage in variant or result types.
type DescriptorStatShape struct {
_ cm.HostLayout
shape [unsafe.Sizeof(DescriptorStat{})]byte
}
// OptionDirectoryEntryShape is used for storage in variant or result types.
type OptionDirectoryEntryShape struct {
_ cm.HostLayout
shape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte
}
+133
View File
@@ -0,0 +1,133 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package types
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0".
//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]descriptor
//go:noescape
func wasmimport_DescriptorResourceDrop(self0 uint32)
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.advise
//go:noescape
func wasmimport_DescriptorAdvise(self0 uint32, offset0 uint64, length0 uint64, advice0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.append-via-stream
//go:noescape
func wasmimport_DescriptorAppendViaStream(self0 uint32, result *cm.Result[OutputStream, OutputStream, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.create-directory-at
//go:noescape
func wasmimport_DescriptorCreateDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-flags
//go:noescape
func wasmimport_DescriptorGetFlags(self0 uint32, result *cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-type
//go:noescape
func wasmimport_DescriptorGetType(self0 uint32, result *cm.Result[DescriptorType, DescriptorType, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.is-same-object
//go:noescape
func wasmimport_DescriptorIsSameObject(self0 uint32, other0 uint32) (result0 uint32)
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.link-at
//go:noescape
func wasmimport_DescriptorLinkAt(self0 uint32, oldPathFlags0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash
//go:noescape
func wasmimport_DescriptorMetadataHash(self0 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash-at
//go:noescape
func wasmimport_DescriptorMetadataHashAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.open-at
//go:noescape
func wasmimport_DescriptorOpenAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, openFlags0 uint32, flags0 uint32, result *cm.Result[Descriptor, Descriptor, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read
//go:noescape
func wasmimport_DescriptorRead(self0 uint32, length0 uint64, offset0 uint64, result *cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-directory
//go:noescape
func wasmimport_DescriptorReadDirectory(self0 uint32, result *cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-via-stream
//go:noescape
func wasmimport_DescriptorReadViaStream(self0 uint32, offset0 uint64, result *cm.Result[InputStream, InputStream, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.readlink-at
//go:noescape
func wasmimport_DescriptorReadLinkAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[string, string, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.remove-directory-at
//go:noescape
func wasmimport_DescriptorRemoveDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.rename-at
//go:noescape
func wasmimport_DescriptorRenameAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-size
//go:noescape
func wasmimport_DescriptorSetSize(self0 uint32, size0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times
//go:noescape
func wasmimport_DescriptorSetTimes(self0 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times-at
//go:noescape
func wasmimport_DescriptorSetTimesAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat
//go:noescape
func wasmimport_DescriptorStat(self0 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat-at
//go:noescape
func wasmimport_DescriptorStatAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.symlink-at
//go:noescape
func wasmimport_DescriptorSymlinkAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync
//go:noescape
func wasmimport_DescriptorSync(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync-data
//go:noescape
func wasmimport_DescriptorSyncData(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.unlink-file-at
//go:noescape
func wasmimport_DescriptorUnlinkFileAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write
//go:noescape
func wasmimport_DescriptorWrite(self0 uint32, buffer0 *uint8, buffer1 uint32, offset0 uint64, result *cm.Result[uint64, FileSize, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write-via-stream
//go:noescape
func wasmimport_DescriptorWriteViaStream(self0 uint32, offset0 uint64, result *cm.Result[OutputStream, OutputStream, ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]directory-entry-stream
//go:noescape
func wasmimport_DirectoryEntryStreamResourceDrop(self0 uint32)
//go:wasmimport wasi:filesystem/types@0.2.0 [method]directory-entry-stream.read-directory-entry
//go:noescape
func wasmimport_DirectoryEntryStreamReadDirectoryEntry(self0 uint32, result *cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode])
//go:wasmimport wasi:filesystem/types@0.2.0 filesystem-error-code
//go:noescape
func wasmimport_FilesystemErrorCode(err0 uint32, result *cm.Option[ErrorCode])
@@ -31,10 +31,29 @@ package types
import (
"internal/cm"
wallclock "internal/wasi/clocks/v0.2.0/wall-clock"
ioerror "internal/wasi/io/v0.2.0/error"
"internal/wasi/io/v0.2.0/streams"
)
// InputStream represents the imported type alias "wasi:filesystem/types@0.2.0#input-stream".
//
// See [streams.InputStream] for more information.
type InputStream = streams.InputStream
// OutputStream represents the imported type alias "wasi:filesystem/types@0.2.0#output-stream".
//
// See [streams.OutputStream] for more information.
type OutputStream = streams.OutputStream
// Error represents the imported type alias "wasi:filesystem/types@0.2.0#error".
//
// See [streams.Error] for more information.
type Error = streams.Error
// DateTime represents the type alias "wasi:filesystem/types@0.2.0#datetime".
//
// See [wallclock.DateTime] for more information.
type DateTime = wallclock.DateTime
// FileSize represents the u64 "wasi:filesystem/types@0.2.0#filesize".
//
// File size or length of a region within a file.
@@ -227,6 +246,7 @@ type LinkCount uint64
// status-change-timestamp: option<datetime>,
// }
type DescriptorStat struct {
_ cm.HostLayout
// File type.
Type DescriptorType
@@ -241,19 +261,19 @@ type DescriptorStat struct {
//
// If the `option` is none, the platform doesn't maintain an access
// timestamp for this file.
DataAccessTimestamp cm.Option[wallclock.DateTime]
DataAccessTimestamp cm.Option[DateTime]
// Last data modification timestamp.
//
// If the `option` is none, the platform doesn't maintain a
// modification timestamp for this file.
DataModificationTimestamp cm.Option[wallclock.DateTime]
DataModificationTimestamp cm.Option[DateTime]
// Last file status-change timestamp.
//
// If the `option` is none, the platform doesn't maintain a
// status-change timestamp for this file.
StatusChangeTimestamp cm.Option[wallclock.DateTime]
StatusChangeTimestamp cm.Option[DateTime]
}
// NewTimestamp represents the variant "wasi:filesystem/types@0.2.0#new-timestamp".
@@ -265,7 +285,7 @@ type DescriptorStat struct {
// now,
// timestamp(datetime),
// }
type NewTimestamp cm.Variant[uint8, wallclock.DateTime, wallclock.DateTime]
type NewTimestamp cm.Variant[uint8, DateTime, DateTime]
// NewTimestampNoChange returns a [NewTimestamp] of case "no-change".
//
@@ -297,13 +317,24 @@ func (self *NewTimestamp) Now() bool {
// NewTimestampTimestamp returns a [NewTimestamp] of case "timestamp".
//
// Set the timestamp to the given value.
func NewTimestampTimestamp(data wallclock.DateTime) NewTimestamp {
func NewTimestampTimestamp(data DateTime) NewTimestamp {
return cm.New[NewTimestamp](2, data)
}
// Timestamp returns a non-nil *[wallclock.DateTime] if [NewTimestamp] represents the variant case "timestamp".
func (self *NewTimestamp) Timestamp() *wallclock.DateTime {
return cm.Case[wallclock.DateTime](self, 2)
// Timestamp returns a non-nil *[DateTime] if [NewTimestamp] represents the variant case "timestamp".
func (self *NewTimestamp) Timestamp() *DateTime {
return cm.Case[DateTime](self, 2)
}
var stringsNewTimestamp = [3]string{
"no-change",
"now",
"timestamp",
}
// String implements [fmt.Stringer], returning the variant case name of v.
func (v NewTimestamp) String() string {
return stringsNewTimestamp[v.Tag()]
}
// DirectoryEntry represents the record "wasi:filesystem/types@0.2.0#directory-entry".
@@ -315,6 +346,7 @@ func (self *NewTimestamp) Timestamp() *wallclock.DateTime {
// name: string,
// }
type DirectoryEntry struct {
_ cm.HostLayout
// The type of the file referred to by this directory entry.
Type DescriptorType
@@ -593,6 +625,7 @@ func (e Advice) String() string {
// upper: u64,
// }
type MetadataHashValue struct {
_ cm.HostLayout
// 64 bits of a 128-bit hash value.
Lower uint64
@@ -620,10 +653,6 @@ func (self Descriptor) ResourceDrop() {
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]descriptor
//go:noescape
func wasmimport_DescriptorResourceDrop(self0 uint32)
// Advise represents the imported method "advise".
//
// Provide file advisory information on a descriptor.
@@ -642,10 +671,6 @@ func (self Descriptor) Advise(offset FileSize, length FileSize, advice Advice) (
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.advise
//go:noescape
func wasmimport_DescriptorAdvise(self0 uint32, offset0 uint64, length0 uint64, advice0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// AppendViaStream represents the imported method "append-via-stream".
//
// Return a stream for appending to a file, if available.
@@ -658,16 +683,12 @@ func wasmimport_DescriptorAdvise(self0 uint32, offset0 uint64, length0 uint64, a
// append-via-stream: func() -> result<output-stream, error-code>
//
//go:nosplit
func (self Descriptor) AppendViaStream() (result cm.Result[streams.OutputStream, streams.OutputStream, ErrorCode]) {
func (self Descriptor) AppendViaStream() (result cm.Result[OutputStream, OutputStream, ErrorCode]) {
self0 := cm.Reinterpret[uint32](self)
wasmimport_DescriptorAppendViaStream((uint32)(self0), &result)
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.append-via-stream
//go:noescape
func wasmimport_DescriptorAppendViaStream(self0 uint32, result *cm.Result[streams.OutputStream, streams.OutputStream, ErrorCode])
// CreateDirectoryAt represents the imported method "create-directory-at".
//
// Create a directory.
@@ -684,10 +705,6 @@ func (self Descriptor) CreateDirectoryAt(path string) (result cm.Result[ErrorCod
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.create-directory-at
//go:noescape
func wasmimport_DescriptorCreateDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// GetFlags represents the imported method "get-flags".
//
// Get flags associated with a descriptor.
@@ -706,10 +723,6 @@ func (self Descriptor) GetFlags() (result cm.Result[DescriptorFlags, DescriptorF
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-flags
//go:noescape
func wasmimport_DescriptorGetFlags(self0 uint32, result *cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode])
// GetType represents the imported method "get-type".
//
// Get the dynamic type of a descriptor.
@@ -732,10 +745,6 @@ func (self Descriptor) GetType() (result cm.Result[DescriptorType, DescriptorTyp
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-type
//go:noescape
func wasmimport_DescriptorGetType(self0 uint32, result *cm.Result[DescriptorType, DescriptorType, ErrorCode])
// IsSameObject represents the imported method "is-same-object".
//
// Test whether two descriptors refer to the same filesystem object.
@@ -756,10 +765,6 @@ func (self Descriptor) IsSameObject(other Descriptor) (result bool) {
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.is-same-object
//go:noescape
func wasmimport_DescriptorIsSameObject(self0 uint32, other0 uint32) (result0 uint32)
// LinkAt represents the imported method "link-at".
//
// Create a hard link.
@@ -780,10 +785,6 @@ func (self Descriptor) LinkAt(oldPathFlags PathFlags, oldPath string, newDescrip
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.link-at
//go:noescape
func wasmimport_DescriptorLinkAt(self0 uint32, oldPathFlags0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// MetadataHash represents the imported method "metadata-hash".
//
// Return a hash of the metadata associated with a filesystem object referred
@@ -815,10 +816,6 @@ func (self Descriptor) MetadataHash() (result cm.Result[MetadataHashValueShape,
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash
//go:noescape
func wasmimport_DescriptorMetadataHash(self0 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])
// MetadataHashAt represents the imported method "metadata-hash-at".
//
// Return a hash of the metadata associated with a filesystem object referred
@@ -838,10 +835,6 @@ func (self Descriptor) MetadataHashAt(pathFlags PathFlags, path string) (result
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash-at
//go:noescape
func wasmimport_DescriptorMetadataHashAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])
// OpenAt represents the imported method "open-at".
//
// Open a file or directory.
@@ -877,10 +870,6 @@ func (self Descriptor) OpenAt(pathFlags PathFlags, path string, openFlags OpenFl
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.open-at
//go:noescape
func wasmimport_DescriptorOpenAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, openFlags0 uint32, flags0 uint32, result *cm.Result[Descriptor, Descriptor, ErrorCode])
// Read represents the imported method "read".
//
// Read from a descriptor, without using and updating the descriptor's offset.
@@ -907,10 +896,6 @@ func (self Descriptor) Read(length FileSize, offset FileSize) (result cm.Result[
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read
//go:noescape
func wasmimport_DescriptorRead(self0 uint32, length0 uint64, offset0 uint64, result *cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode])
// ReadDirectory represents the imported method "read-directory".
//
// Read directory entries from a directory.
@@ -932,10 +917,6 @@ func (self Descriptor) ReadDirectory() (result cm.Result[DirectoryEntryStream, D
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-directory
//go:noescape
func wasmimport_DescriptorReadDirectory(self0 uint32, result *cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode])
// ReadViaStream represents the imported method "read-via-stream".
//
// Return a stream for reading from a file, if available.
@@ -950,17 +931,13 @@ func wasmimport_DescriptorReadDirectory(self0 uint32, result *cm.Result[Director
// read-via-stream: func(offset: filesize) -> result<input-stream, error-code>
//
//go:nosplit
func (self Descriptor) ReadViaStream(offset FileSize) (result cm.Result[streams.InputStream, streams.InputStream, ErrorCode]) {
func (self Descriptor) ReadViaStream(offset FileSize) (result cm.Result[InputStream, InputStream, ErrorCode]) {
self0 := cm.Reinterpret[uint32](self)
offset0 := (uint64)(offset)
wasmimport_DescriptorReadViaStream((uint32)(self0), (uint64)(offset0), &result)
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-via-stream
//go:noescape
func wasmimport_DescriptorReadViaStream(self0 uint32, offset0 uint64, result *cm.Result[streams.InputStream, streams.InputStream, ErrorCode])
// ReadLinkAt represents the imported method "readlink-at".
//
// Read the contents of a symbolic link.
@@ -980,10 +957,6 @@ func (self Descriptor) ReadLinkAt(path string) (result cm.Result[string, string,
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.readlink-at
//go:noescape
func wasmimport_DescriptorReadLinkAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[string, string, ErrorCode])
// RemoveDirectoryAt represents the imported method "remove-directory-at".
//
// Remove a directory.
@@ -1002,10 +975,6 @@ func (self Descriptor) RemoveDirectoryAt(path string) (result cm.Result[ErrorCod
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.remove-directory-at
//go:noescape
func wasmimport_DescriptorRemoveDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// RenameAt represents the imported method "rename-at".
//
// Rename a filesystem object.
@@ -1025,10 +994,6 @@ func (self Descriptor) RenameAt(oldPath string, newDescriptor Descriptor, newPat
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.rename-at
//go:noescape
func wasmimport_DescriptorRenameAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// SetSize represents the imported method "set-size".
//
// Adjust the size of an open file. If this increases the file's size, the
@@ -1046,10 +1011,6 @@ func (self Descriptor) SetSize(size FileSize) (result cm.Result[ErrorCode, struc
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-size
//go:noescape
func wasmimport_DescriptorSetSize(self0 uint32, size0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// SetTimes represents the imported method "set-times".
//
// Adjust the timestamps of an open file or directory.
@@ -1070,10 +1031,6 @@ func (self Descriptor) SetTimes(dataAccessTimestamp NewTimestamp, dataModificati
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times
//go:noescape
func wasmimport_DescriptorSetTimes(self0 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// SetTimesAt represents the imported method "set-times-at".
//
// Adjust the timestamps of a file or directory.
@@ -1097,10 +1054,6 @@ func (self Descriptor) SetTimesAt(pathFlags PathFlags, path string, dataAccessTi
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times-at
//go:noescape
func wasmimport_DescriptorSetTimesAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// Stat represents the imported method "stat".
//
// Return the attributes of an open file or directory.
@@ -1122,10 +1075,6 @@ func (self Descriptor) Stat() (result cm.Result[DescriptorStatShape, DescriptorS
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat
//go:noescape
func wasmimport_DescriptorStat(self0 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])
// StatAt represents the imported method "stat-at".
//
// Return the attributes of a file or directory.
@@ -1148,10 +1097,6 @@ func (self Descriptor) StatAt(pathFlags PathFlags, path string) (result cm.Resul
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat-at
//go:noescape
func wasmimport_DescriptorStatAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])
// SymlinkAt represents the imported method "symlink-at".
//
// Create a symbolic link (also known as a "symlink").
@@ -1172,10 +1117,6 @@ func (self Descriptor) SymlinkAt(oldPath string, newPath string) (result cm.Resu
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.symlink-at
//go:noescape
func wasmimport_DescriptorSymlinkAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// Sync represents the imported method "sync".
//
// Synchronize the data and metadata of a file to disk.
@@ -1194,10 +1135,6 @@ func (self Descriptor) Sync() (result cm.Result[ErrorCode, struct{}, ErrorCode])
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync
//go:noescape
func wasmimport_DescriptorSync(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// SyncData represents the imported method "sync-data".
//
// Synchronize the data of a file to disk.
@@ -1216,10 +1153,6 @@ func (self Descriptor) SyncData() (result cm.Result[ErrorCode, struct{}, ErrorCo
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync-data
//go:noescape
func wasmimport_DescriptorSyncData(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// UnlinkFileAt represents the imported method "unlink-file-at".
//
// Unlink a filesystem object that is not a directory.
@@ -1237,10 +1170,6 @@ func (self Descriptor) UnlinkFileAt(path string) (result cm.Result[ErrorCode, st
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.unlink-file-at
//go:noescape
func wasmimport_DescriptorUnlinkFileAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
// Write represents the imported method "write".
//
// Write to a descriptor, without using and updating the descriptor's offset.
@@ -1264,10 +1193,6 @@ func (self Descriptor) Write(buffer cm.List[uint8], offset FileSize) (result cm.
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write
//go:noescape
func wasmimport_DescriptorWrite(self0 uint32, buffer0 *uint8, buffer1 uint32, offset0 uint64, result *cm.Result[uint64, FileSize, ErrorCode])
// WriteViaStream represents the imported method "write-via-stream".
//
// Return a stream for writing to a file, if available.
@@ -1280,17 +1205,13 @@ func wasmimport_DescriptorWrite(self0 uint32, buffer0 *uint8, buffer1 uint32, of
// write-via-stream: func(offset: filesize) -> result<output-stream, error-code>
//
//go:nosplit
func (self Descriptor) WriteViaStream(offset FileSize) (result cm.Result[streams.OutputStream, streams.OutputStream, ErrorCode]) {
func (self Descriptor) WriteViaStream(offset FileSize) (result cm.Result[OutputStream, OutputStream, ErrorCode]) {
self0 := cm.Reinterpret[uint32](self)
offset0 := (uint64)(offset)
wasmimport_DescriptorWriteViaStream((uint32)(self0), (uint64)(offset0), &result)
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write-via-stream
//go:noescape
func wasmimport_DescriptorWriteViaStream(self0 uint32, offset0 uint64, result *cm.Result[streams.OutputStream, streams.OutputStream, ErrorCode])
// DirectoryEntryStream represents the imported resource "wasi:filesystem/types@0.2.0#directory-entry-stream".
//
// A stream of directory entries.
@@ -1309,10 +1230,6 @@ func (self DirectoryEntryStream) ResourceDrop() {
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]directory-entry-stream
//go:noescape
func wasmimport_DirectoryEntryStreamResourceDrop(self0 uint32)
// ReadDirectoryEntry represents the imported method "read-directory-entry".
//
// Read a single directory entry from a `directory-entry-stream`.
@@ -1326,10 +1243,6 @@ func (self DirectoryEntryStream) ReadDirectoryEntry() (result cm.Result[OptionDi
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 [method]directory-entry-stream.read-directory-entry
//go:noescape
func wasmimport_DirectoryEntryStreamReadDirectoryEntry(self0 uint32, result *cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode])
// FilesystemErrorCode represents the imported function "filesystem-error-code".
//
// Attempts to extract a filesystem-related `error-code` from the stream
@@ -1346,12 +1259,8 @@ func wasmimport_DirectoryEntryStreamReadDirectoryEntry(self0 uint32, result *cm.
// filesystem-error-code: func(err: borrow<error>) -> option<error-code>
//
//go:nosplit
func FilesystemErrorCode(err ioerror.Error) (result cm.Option[ErrorCode]) {
func FilesystemErrorCode(err Error) (result cm.Option[ErrorCode]) {
err0 := cm.Reinterpret[uint32](err)
wasmimport_FilesystemErrorCode((uint32)(err0), &result)
return
}
//go:wasmimport wasi:filesystem/types@0.2.0 filesystem-error-code
//go:noescape
func wasmimport_FilesystemErrorCode(err0 uint32, result *cm.Option[ErrorCode])
@@ -43,10 +43,6 @@ func (self Error) ResourceDrop() {
return
}
//go:wasmimport wasi:io/error@0.2.0 [resource-drop]error
//go:noescape
func wasmimport_ErrorResourceDrop(self0 uint32)
// ToDebugString represents the imported method "to-debug-string".
//
// Returns a string that is suitable to assist humans in debugging
@@ -65,7 +61,3 @@ func (self Error) ToDebugString() (result string) {
wasmimport_ErrorToDebugString((uint32)(self0), &result)
return
}
//go:wasmimport wasi:io/error@0.2.0 [method]error.to-debug-string
//go:noescape
func wasmimport_ErrorToDebugString(self0 uint32, result *string)
+13
View File
@@ -0,0 +1,13 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package ioerror
// This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0".
//go:wasmimport wasi:io/error@0.2.0 [resource-drop]error
//go:noescape
func wasmimport_ErrorResourceDrop(self0 uint32)
//go:wasmimport wasi:io/error@0.2.0 [method]error.to-debug-string
//go:noescape
func wasmimport_ErrorToDebugString(self0 uint32, result *string)
+25
View File
@@ -0,0 +1,25 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package poll
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0".
//go:wasmimport wasi:io/poll@0.2.0 [resource-drop]pollable
//go:noescape
func wasmimport_PollableResourceDrop(self0 uint32)
//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.block
//go:noescape
func wasmimport_PollableBlock(self0 uint32)
//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.ready
//go:noescape
func wasmimport_PollableReady(self0 uint32) (result0 uint32)
//go:wasmimport wasi:io/poll@0.2.0 poll
//go:noescape
func wasmimport_Poll(in0 *Pollable, in1 uint32, result *cm.List[uint32])
@@ -28,10 +28,6 @@ func (self Pollable) ResourceDrop() {
return
}
//go:wasmimport wasi:io/poll@0.2.0 [resource-drop]pollable
//go:noescape
func wasmimport_PollableResourceDrop(self0 uint32)
// Block represents the imported method "block".
//
// `block` returns immediately if the pollable is ready, and otherwise
@@ -49,10 +45,6 @@ func (self Pollable) Block() {
return
}
//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.block
//go:noescape
func wasmimport_PollableBlock(self0 uint32)
// Ready represents the imported method "ready".
//
// Return the readiness of a pollable. This function never blocks.
@@ -69,10 +61,6 @@ func (self Pollable) Ready() (result bool) {
return
}
//go:wasmimport wasi:io/poll@0.2.0 [method]pollable.ready
//go:noescape
func wasmimport_PollableReady(self0 uint32) (result0 uint32)
// Poll represents the imported function "poll".
//
// Poll for completion on a set of pollables.
@@ -102,7 +90,3 @@ func Poll(in cm.List[Pollable]) (result cm.List[uint32]) {
wasmimport_Poll((*Pollable)(in0), (uint32)(in1), &result)
return
}
//go:wasmimport wasi:io/poll@0.2.0 poll
//go:noescape
func wasmimport_Poll(in0 *Pollable, in1 uint32, result *cm.List[uint32])
+77
View File
@@ -0,0 +1,77 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package streams
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:io@0.2.0".
//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]input-stream
//go:noescape
func wasmimport_InputStreamResourceDrop(self0 uint32)
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-read
//go:noescape
func wasmimport_InputStreamBlockingRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-skip
//go:noescape
func wasmimport_InputStreamBlockingSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.read
//go:noescape
func wasmimport_InputStreamRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.skip
//go:noescape
func wasmimport_InputStreamSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.subscribe
//go:noescape
func wasmimport_InputStreamSubscribe(self0 uint32) (result0 uint32)
//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]output-stream
//go:noescape
func wasmimport_OutputStreamResourceDrop(self0 uint32)
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-flush
//go:noescape
func wasmimport_OutputStreamBlockingFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-splice
//go:noescape
func wasmimport_OutputStreamBlockingSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-and-flush
//go:noescape
func wasmimport_OutputStreamBlockingWriteAndFlush(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-zeroes-and-flush
//go:noescape
func wasmimport_OutputStreamBlockingWriteZeroesAndFlush(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.check-write
//go:noescape
func wasmimport_OutputStreamCheckWrite(self0 uint32, result *cm.Result[uint64, uint64, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.flush
//go:noescape
func wasmimport_OutputStreamFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.splice
//go:noescape
func wasmimport_OutputStreamSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.subscribe
//go:noescape
func wasmimport_OutputStreamSubscribe(self0 uint32) (result0 uint32)
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write
//go:noescape
func wasmimport_OutputStreamWrite(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError])
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write-zeroes
//go:noescape
func wasmimport_OutputStreamWriteZeroes(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError])
@@ -15,6 +15,16 @@ import (
"internal/wasi/io/v0.2.0/poll"
)
// Error represents the imported type alias "wasi:io/streams@0.2.0#error".
//
// See [ioerror.Error] for more information.
type Error = ioerror.Error
// Pollable represents the imported type alias "wasi:io/streams@0.2.0#pollable".
//
// See [poll.Pollable] for more information.
type Pollable = poll.Pollable
// StreamError represents the imported variant "wasi:io/streams@0.2.0#stream-error".
//
// An error for input-stream and output-stream operations.
@@ -23,20 +33,20 @@ import (
// last-operation-failed(error),
// closed,
// }
type StreamError cm.Variant[uint8, ioerror.Error, ioerror.Error]
type StreamError cm.Variant[uint8, Error, Error]
// StreamErrorLastOperationFailed returns a [StreamError] of case "last-operation-failed".
//
// The last operation (a write or flush) failed before completion.
//
// More information is available in the `error` payload.
func StreamErrorLastOperationFailed(data ioerror.Error) StreamError {
func StreamErrorLastOperationFailed(data Error) StreamError {
return cm.New[StreamError](0, data)
}
// LastOperationFailed returns a non-nil *[ioerror.Error] if [StreamError] represents the variant case "last-operation-failed".
func (self *StreamError) LastOperationFailed() *ioerror.Error {
return cm.Case[ioerror.Error](self, 0)
// LastOperationFailed returns a non-nil *[Error] if [StreamError] represents the variant case "last-operation-failed".
func (self *StreamError) LastOperationFailed() *Error {
return cm.Case[Error](self, 0)
}
// StreamErrorClosed returns a [StreamError] of case "closed".
@@ -54,6 +64,16 @@ func (self *StreamError) Closed() bool {
return self.Tag() == 1
}
var stringsStreamError = [2]string{
"last-operation-failed",
"closed",
}
// String implements [fmt.Stringer], returning the variant case name of v.
func (v StreamError) String() string {
return stringsStreamError[v.Tag()]
}
// InputStream represents the imported resource "wasi:io/streams@0.2.0#input-stream".
//
// An input bytestream.
@@ -79,10 +99,6 @@ func (self InputStream) ResourceDrop() {
return
}
//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]input-stream
//go:noescape
func wasmimport_InputStreamResourceDrop(self0 uint32)
// BlockingRead represents the imported method "blocking-read".
//
// Read bytes from a stream, after blocking until at least one byte can
@@ -98,10 +114,6 @@ func (self InputStream) BlockingRead(len_ uint64) (result cm.Result[cm.List[uint
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-read
//go:noescape
func wasmimport_InputStreamBlockingRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError])
// BlockingSkip represents the imported method "blocking-skip".
//
// Skip bytes from a stream, after blocking until at least one byte
@@ -117,10 +129,6 @@ func (self InputStream) BlockingSkip(len_ uint64) (result cm.Result[uint64, uint
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.blocking-skip
//go:noescape
func wasmimport_InputStreamBlockingSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
// Read represents the imported method "read".
//
// Perform a non-blocking read from the stream.
@@ -160,10 +168,6 @@ func (self InputStream) Read(len_ uint64) (result cm.Result[cm.List[uint8], cm.L
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.read
//go:noescape
func wasmimport_InputStreamRead(self0 uint32, len0 uint64, result *cm.Result[cm.List[uint8], cm.List[uint8], StreamError])
// Skip represents the imported method "skip".
//
// Skip bytes from a stream. Returns number of bytes skipped.
@@ -181,10 +185,6 @@ func (self InputStream) Skip(len_ uint64) (result cm.Result[uint64, uint64, Stre
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.skip
//go:noescape
func wasmimport_InputStreamSkip(self0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
// Subscribe represents the imported method "subscribe".
//
// Create a `pollable` which will resolve once either the specified stream
@@ -197,17 +197,13 @@ func wasmimport_InputStreamSkip(self0 uint32, len0 uint64, result *cm.Result[uin
// subscribe: func() -> pollable
//
//go:nosplit
func (self InputStream) Subscribe() (result poll.Pollable) {
func (self InputStream) Subscribe() (result Pollable) {
self0 := cm.Reinterpret[uint32](self)
result0 := wasmimport_InputStreamSubscribe((uint32)(self0))
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
result = cm.Reinterpret[Pollable]((uint32)(result0))
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]input-stream.subscribe
//go:noescape
func wasmimport_InputStreamSubscribe(self0 uint32) (result0 uint32)
// OutputStream represents the imported resource "wasi:io/streams@0.2.0#output-stream".
//
// An output bytestream.
@@ -233,10 +229,6 @@ func (self OutputStream) ResourceDrop() {
return
}
//go:wasmimport wasi:io/streams@0.2.0 [resource-drop]output-stream
//go:noescape
func wasmimport_OutputStreamResourceDrop(self0 uint32)
// BlockingFlush represents the imported method "blocking-flush".
//
// Request to flush buffered output, and block until flush completes
@@ -251,10 +243,6 @@ func (self OutputStream) BlockingFlush() (result cm.Result[StreamError, struct{}
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-flush
//go:noescape
func wasmimport_OutputStreamBlockingFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError])
// BlockingSplice represents the imported method "blocking-splice".
//
// Read from one stream and write to another, with blocking.
@@ -274,10 +262,6 @@ func (self OutputStream) BlockingSplice(src InputStream, len_ uint64) (result cm
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-splice
//go:noescape
func wasmimport_OutputStreamBlockingSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
// BlockingWriteAndFlush represents the imported method "blocking-write-and-flush".
//
// Perform a write of up to 4096 bytes, and then flush the stream. Block
@@ -313,10 +297,6 @@ func (self OutputStream) BlockingWriteAndFlush(contents cm.List[uint8]) (result
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-and-flush
//go:noescape
func wasmimport_OutputStreamBlockingWriteAndFlush(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError])
// BlockingWriteZeroesAndFlush represents the imported method "blocking-write-zeroes-and-flush".
//
// Perform a write of up to 4096 zeroes, and then flush the stream.
@@ -352,10 +332,6 @@ func (self OutputStream) BlockingWriteZeroesAndFlush(len_ uint64) (result cm.Res
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.blocking-write-zeroes-and-flush
//go:noescape
func wasmimport_OutputStreamBlockingWriteZeroesAndFlush(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError])
// CheckWrite represents the imported method "check-write".
//
// Check readiness for writing. This function never blocks.
@@ -377,10 +353,6 @@ func (self OutputStream) CheckWrite() (result cm.Result[uint64, uint64, StreamEr
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.check-write
//go:noescape
func wasmimport_OutputStreamCheckWrite(self0 uint32, result *cm.Result[uint64, uint64, StreamError])
// Flush represents the imported method "flush".
//
// Request to flush buffered output. This function never blocks.
@@ -403,10 +375,6 @@ func (self OutputStream) Flush() (result cm.Result[StreamError, struct{}, Stream
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.flush
//go:noescape
func wasmimport_OutputStreamFlush(self0 uint32, result *cm.Result[StreamError, struct{}, StreamError])
// Splice represents the imported method "splice".
//
// Read from one stream and write to another.
@@ -434,10 +402,6 @@ func (self OutputStream) Splice(src InputStream, len_ uint64) (result cm.Result[
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.splice
//go:noescape
func wasmimport_OutputStreamSplice(self0 uint32, src0 uint32, len0 uint64, result *cm.Result[uint64, uint64, StreamError])
// Subscribe represents the imported method "subscribe".
//
// Create a `pollable` which will resolve once the output-stream
@@ -454,17 +418,13 @@ func wasmimport_OutputStreamSplice(self0 uint32, src0 uint32, len0 uint64, resul
// subscribe: func() -> pollable
//
//go:nosplit
func (self OutputStream) Subscribe() (result poll.Pollable) {
func (self OutputStream) Subscribe() (result Pollable) {
self0 := cm.Reinterpret[uint32](self)
result0 := wasmimport_OutputStreamSubscribe((uint32)(self0))
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
result = cm.Reinterpret[Pollable]((uint32)(result0))
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.subscribe
//go:noescape
func wasmimport_OutputStreamSubscribe(self0 uint32) (result0 uint32)
// Write represents the imported method "write".
//
// Perform a write. This function never blocks.
@@ -491,10 +451,6 @@ func (self OutputStream) Write(contents cm.List[uint8]) (result cm.Result[Stream
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write
//go:noescape
func wasmimport_OutputStreamWrite(self0 uint32, contents0 *uint8, contents1 uint32, result *cm.Result[StreamError, struct{}, StreamError])
// WriteZeroes represents the imported method "write-zeroes".
//
// Write zeroes to a stream.
@@ -513,7 +469,3 @@ func (self OutputStream) WriteZeroes(len_ uint64) (result cm.Result[StreamError,
wasmimport_OutputStreamWriteZeroes((uint32)(self0), (uint64)(len0), &result)
return
}
//go:wasmimport wasi:io/streams@0.2.0 [method]output-stream.write-zeroes
//go:noescape
func wasmimport_OutputStreamWriteZeroes(self0 uint32, len0 uint64, result *cm.Result[StreamError, struct{}, StreamError])
@@ -35,7 +35,3 @@ func InsecureSeed() (result [2]uint64) {
wasmimport_InsecureSeed(&result)
return
}
//go:wasmimport wasi:random/insecure-seed@0.2.0 insecure-seed
//go:noescape
func wasmimport_InsecureSeed(result *[2]uint64)
@@ -0,0 +1,9 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package insecureseed
// This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0".
//go:wasmimport wasi:random/insecure-seed@0.2.0 insecure-seed
//go:noescape
func wasmimport_InsecureSeed(result *[2]uint64)
+17
View File
@@ -0,0 +1,17 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package insecure
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0".
//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-bytes
//go:noescape
func wasmimport_GetInsecureRandomBytes(len0 uint64, result *cm.List[uint8])
//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64
//go:noescape
func wasmimport_GetInsecureRandomU64() (result0 uint64)
@@ -32,10 +32,6 @@ func GetInsecureRandomBytes(len_ uint64) (result cm.List[uint8]) {
return
}
//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-bytes
//go:noescape
func wasmimport_GetInsecureRandomBytes(len0 uint64, result *cm.List[uint8])
// GetInsecureRandomU64 represents the imported function "get-insecure-random-u64".
//
// Return an insecure pseudo-random `u64` value.
@@ -51,7 +47,3 @@ func GetInsecureRandomU64() (result uint64) {
result = (uint64)((uint64)(result0))
return
}
//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64
//go:noescape
func wasmimport_GetInsecureRandomU64() (result0 uint64)
+17
View File
@@ -0,0 +1,17 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
package random
import (
"internal/cm"
)
// This file contains wasmimport and wasmexport declarations for "wasi:random@0.2.0".
//go:wasmimport wasi:random/random@0.2.0 get-random-bytes
//go:noescape
func wasmimport_GetRandomBytes(len0 uint64, result *cm.List[uint8])
//go:wasmimport wasi:random/random@0.2.0 get-random-u64
//go:noescape
func wasmimport_GetRandomU64() (result0 uint64)
@@ -36,10 +36,6 @@ func GetRandomBytes(len_ uint64) (result cm.List[uint8]) {
return
}
//go:wasmimport wasi:random/random@0.2.0 get-random-bytes
//go:noescape
func wasmimport_GetRandomBytes(len0 uint64, result *cm.List[uint8])
// GetRandomU64 represents the imported function "get-random-u64".
//
// Return a cryptographically-secure random or pseudo-random `u64` value.
@@ -55,7 +51,3 @@ func GetRandomU64() (result uint64) {
result = (uint64)((uint64)(result0))
return
}
//go:wasmimport wasi:random/random@0.2.0 get-random-u64
//go:noescape
func wasmimport_GetRandomU64() (result0 uint64)

Some files were not shown because too many files have changed in this diff Show More