Compare commits

..

31 Commits

Author SHA1 Message Date
Ayke van Laethem 587ad68bd9 loader: report all type and syntax errors possible
Previously the loader would only report the first error. With this
change, all syntax and type errors will be reported.
2024-07-12 15:09:25 +02:00
Ayke van Laethem a6602dc708 loader: handle go list errors inside TinyGo
Instead of exiting with an error, handle these errors internally.
This will enable a few improvements in the future.
2024-07-10 11:58:36 +02:00
Ayke van Laethem 3de78fcdc6 libclang: do not make error locations relative
This is done at a later time anyway, so doesn't need to be done in the
cgo package. In fact, _not_ doing it there makes it easier to print
correct relative packages.
2024-07-09 17:26:08 +02:00
Ayke van Laethem 3610c93b9e all: add testing for compiler error messages
This is needed for some improvements I'm going to make next.

This commit also refactors error handling slightly to make it more
easily testable, this should hopefully not result in any actual changes
in behavior.
2024-07-09 17:16:32 +02:00
L. Pereira ac396708da main_test: Diff expected and actual results when tests fail (#4288)
Uses a vendored "internal/diff" from Big Go to show the differences
between the expected and actual outputs when tests fail.

Signed-off-by: L. Pereira <l.pereira@fastly.com>
2024-07-08 16:35:06 -07:00
L. Pereira d150badf33 gc_leaking: Don't zero out new allocations in some targets (#4302)
Wasm linear memory is always initialized to zero by definition,
so there's no need to waste time zeroing out this allocation. This
is the case for freshly-obtained memory from mmap().

Signed-off-by: L. Pereira <l.pereira@fastly.com>
2024-07-08 16:34:40 -07:00
Randy Reddig 2d85fc6a64 internal/wasi: update to wasm-tools-go@v0.1.2 (#4326)
* internal/wasi: update to wasm-tools-go@v0.1.1

See https://github.com/ydnar/wasm-tools-go/releases/tag/v0.1.1 for additional information.

* internal/wasi: update to wasm-tools-go@v0.1.2

* internal/wasi: regenerate with wasm-tools-go@v0.1.3
2024-07-08 13:09:47 -07:00
Elias Naur 5ca3e4a2da runtime: implement dummy getAuxv to satisfy golang.org/x/sys/cpu (#4325)
Fixes the program

  package main

  import _ "golang.org/x/sys/cpu"

  func main() {
  }
2024-07-08 13:09:30 -07:00
Ayke van Laethem e6caa3fe9e transform: fix incorrect alignment of heap-to-stack transform
It assumed the maximum alignment was equal to sizeof(void*), which is
definitely not the case. So this only worked more or less by accident
previously.

It now uses the alignment as specified by the frontend, or else
`unsafe.Alignof(complex128)` which is typically the maximum alignment of
a given platform (though this shouldn't really happen in practice: the
optimizer should keep the 'align' attribute in place).
2024-07-03 07:31:37 +02:00
Ayke van Laethem 571447c7c1 compiler: add 'align' attribute to runtime.alloc calls
This adds something like 'align 4' to the runtime.alloc calls, so that
the compiler knows the alignment of the allocation and can optimize
accordingly.

The optimization is very small, only 0.01% in my small test. However, my
plan is to read the value in the heap-to-stack transform pass to make it
more correct and let it produce slightly more optimal code.
2024-07-03 07:31:37 +02:00
Damian Gryski 9cb263479c wasi preview 2 support (#4027)
* all: wasip2 support

Co-authored-by: Randy Reddig <randy.reddig@fastly.com>
2024-07-02 07:02:03 -07:00
Ayke van Laethem f18c6e342f test: support GOOS/GOARCH pairs in the -target flag
This means it's possible to test just a particular OS/arch with a
command like this:

    go test -run=Build -target=linux/arm

I found it useful while working on MIPS support.
2024-06-28 12:31:38 +02:00
leongross 2d5a8d407b add support for unix.{RawSyscall,RawSyscallNoError} 2024-06-27 21:14:22 +02:00
leongross 36958b2875 add support for unix.Syscall* invocations
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-27 21:14:22 +02:00
Ayke van Laethem fae0402fde wasm-unknown: make sure the os package can be imported
See: https://github.com/tinygo-org/tinygo/issues/4314

The os package isn't particularly useful on wasm-unknown, but just like
on baremetal systems it's imported by a lot of packages so it should at
least be possible to import this package.
2024-06-27 21:11:11 +02:00
deadprogram 4517a0c17b version: update to 0.33.0-dev
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-06-25 22:18:20 +02:00
Ayke van Laethem 6abaee4640 compiler: remove old atomics workaround for AVR
The bug should have been fixed in any LLVM version that we currently
support.
2024-06-25 09:27:31 +02:00
Ayke van Laethem 1270a50104 machine: use new internal/binary package
The encoding/binary package in Go 1.23 imports the slices package, which
results in circular import when imported from the machine package.
Therefore, encoding/binary cannot be used in the machine package.

This commit fixes that by introducing a new internal/binary package that
is just plain Go code without dependencies. It can be safely used
anywhere (including the runtime if needed).
2024-06-24 21:21:52 +02:00
Ayke van Laethem 868262f4a7 all: use latest version of x/tools
We previously picked a work-in-progress patch, but this is the proper
fix for this race condition. I think we should use that instead of
relying on the previous work-in-progress patch.
2024-06-23 19:11:06 +02:00
leongross d33ace7b59 remove unused registers for x86_64 linux syscalls
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-23 07:47:34 +02:00
Ayke van Laethem dd6fa89aa6 Release 0.32.0 2024-06-16 18:24:36 +02:00
leongross d513cae5d2 add SetReadDeadline stub 2024-06-15 11:34:06 +02:00
Ayke van Laethem e612f7cf3f Add smoke tests for machine package
The machine package wasn't tested for every board. Therefore, add a new
serial-like test that also tries to import the machine package. This
should highlight potential issues in the future.
2024-06-14 17:28:31 +02:00
Ayke van Laethem 385a7920e6 compiler: fix race condition by applying a proposed patch
This commit switches to v0.22.0 of golang.org/x/tools and then applies
https://go-review.googlesource.com/c/tools/+/590815 to fix the race
condition.

In my testing, it seems to fix these issues.
2024-06-12 14:46:47 +02:00
Ayke van Laethem 077b35e9ad all: drop support for Go 1.18
Go 1.18 has been unsupported for quite a while now (the oldest supported
version is Go 1.21). But more importantly, the golang.org/x/tools module
now requires Go 1.19 or later. So we'll drop this older version.
2024-06-12 14:46:47 +02:00
deadprogram 880e940417 targets: add cyw43439 tag to badger2040-w and also add new pico-w target for wireless support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-06-11 07:57:58 +02:00
L. Pereira ad6c89bf64 transform/rtcalls: Bail fast if can't convert pointer
There's no need to keep looping if one of the uses makes it impossible
to convert a call to `runtime.stringToBytes()` with a raw pointer.

Signed-off-by: L. Pereira <l.pereira@fastly.com>
2024-06-10 12:39:55 +02:00
Ayke van Laethem ae6220262a cgo: implement shift operations in preprocessor macros 2024-06-07 20:40:27 +02:00
leongross e731a31eb9 update fpm ci, fixup import
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-06 16:24:33 +02:00
leongross 3023ba584b Add process.Release for unix
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-06 16:24:33 +02:00
leongross 3a8ef33c72 add FindProcess for posix
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-06 16:24:33 +02:00
195 changed files with 8220 additions and 346 deletions
+3 -3
View File
@@ -98,9 +98,9 @@ commands:
- /go/pkg/mod
jobs:
test-llvm15-go118:
test-llvm15-go119:
docker:
- image: golang:1.18-bullseye
- image: golang:1.19-bullseye
steps:
- test-linux:
llvm: "15"
@@ -118,6 +118,6 @@ workflows:
jobs:
# This tests our lowest supported versions of Go and LLVM, to make sure at
# least the smoke tests still pass.
- test-llvm15-go118
- test-llvm15-go119
# This tests LLVM 18 support when linking against system libraries.
- test-llvm18-go122
+13 -11
View File
@@ -134,17 +134,19 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- name: Install wasmtime
run: |
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
curl https://github.com/bytecodealliance/wasmtime/releases/download/v14.0.4/wasmtime-v14.0.4-x86_64-linux.tar.xz -o wasmtime-v14.0.4-x86_64-linux.tar.xz -SfL
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v14.0.4-x86_64-linux.tar.xz --strip-components=1 wasmtime-v14.0.4-x86_64-linux/*
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "19.0.1"
- name: Install wasm-tools
uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Download release artifact
uses: actions/download-artifact@v4
with:
@@ -154,8 +156,8 @@ jobs:
mkdir -p ~/lib
tar -C ~/lib -xf tinygo.linux-amd64.tar.gz
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
- run: make tinygo-test-wasi-fast
- run: make tinygo-test-wasip1-fast
- run: make tinygo-test-wasip2-fast
- run: make smoketest
assert-test-linux:
# Run all tests that can run on Linux, with LLVM assertions enabled to catch
@@ -187,11 +189,11 @@ jobs:
with:
node-version: '18'
- name: Install wasmtime
run: |
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v14.0.4/wasmtime-v14.0.4-x86_64-linux.tar.xz -o wasmtime-v14.0.4-x86_64-linux.tar.xz -SfL
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v14.0.4-x86_64-linux.tar.xz --strip-components=1 wasmtime-v14.0.4-x86_64-linux/*
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "19.0.1"
- name: Setup `wasm-tools`
uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
id: cache-llvm-source
+2 -2
View File
@@ -220,5 +220,5 @@ jobs:
shell: bash
working-directory: build
run: 7z x release.zip -r
- name: Test stdlib packages on wasi
run: make tinygo-test-wasi-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo
- name: Test stdlib packages on wasip1
run: make tinygo-test-wasip1-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo
+4 -1
View File
@@ -1,3 +1,6 @@
go.work
go.work.sum
docs/_build
src/device/avr/*.go
src/device/avr/*.ld
@@ -17,7 +20,7 @@ src/device/kendryte/*.go
src/device/kendryte/*.s
src/device/rp/*.go
src/device/rp/*.s
vendor
./vendor
llvm-build
llvm-project
build/*
+6
View File
@@ -39,3 +39,9 @@
path = src/net
url = https://github.com/tinygo-org/net.git
branch = dev
[submodule "lib/wasi-cli"]
path = lib/wasi-cli
url = https://github.com/WebAssembly/wasi-cli
[submodule "src/vendor/github.com/ydnar/wasm-tools-go"]
path = src/vendor/github.com/ydnar/wasm-tools-go
url = https://github.com/ydnar/wasm-tools-go.git
+1 -1
View File
@@ -18,7 +18,7 @@ tarball. If you want to help with development of TinyGo itself, you should follo
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
build tools to be built. Go is of course necessary to build TinyGo itself.
* Go (1.18+)
* Go (1.19+)
* GNU Make
* Standard build tools (gcc/clang)
* git
+58
View File
@@ -1,3 +1,61 @@
0.32.0
---
* **general**
- fix wasi-libc include headers on Nix
- apply OpenOCD commands after target configuration
- fix a minor race condition when determining the build tags
- support UF2 drives with a space in their name on Linux
- add LLVM 18 support
- drop support for Go 1.18 to be able to stay up to date
* **compiler**
- move `-panic=trap` support to the compiler/runtime
- fix symbol table index for WebAssembly archives
- fix ed25519 build errors by adjusting the alias names
- add aliases to generic AES functions
- fix race condition by temporarily applying a proposed patch
- `builder`: keep un-wasm-opt'd .wasm if -work was passed
- `builder`: make sure wasm-opt command line is printed if asked
- `cgo`: implement shift operations in preprocessor macros
- `interp`: checking for methodset existance
* **standard library**
- `machine`: add `__tinygo_spi_tx` function to simulator
- `machine`: fix simulator I2C support
- `machine`: add GetRNG support to simulator
- `machine`: add `TxFifoFreeLevel` for CAN
- `os`: add `Link`
- `os`: add `FindProcess` for posix
- `os`: add `Process.Release` for unix
- `os`: add `SetReadDeadline` stub
- `os`, `os/signal`: add signal stubs
- `os/user`: add stubs for `Lookup{,Group}` and `Group`
- `reflect`: use int in `StringHeader` and `SliceHeader` on non-AVR platforms
- `reflect`: fix `NumMethods` for Interface type
- `runtime`: skip negative sleep durations in sleepTicks
* **targets**
- `esp32`: add I2C support
- `rp2040`: move UART0 and UART1 to common file
- `rp2040`: make all RP2040 boards available for simulation
- `rp2040`: fix timeUnit type
- `stm32`: add i2c `Frequency` and `SetBaudRate` function for chips that were missing implementation
- `wasm-unknown`: add math and memory builtins that LLVM needs
- `wasip1`: replace existing `-target=wasi` support with wasip1 as supported in Go 1.21+
* **boards**
- `adafruit-esp32-feather-v2`: add the Adafruit ESP32 Feather V2
- `badger2040-w`: add support for the Badger2040 W
- `feather-nrf52840-sense`: fix lack of LXFO
- `m5paper`: add support for the M5 Paper
- `mksnanov3`: limit programming speed to 1800 kHz
- `nucleol476rg`: add stm32 nucleol476rg support
- `pico-w`: add the Pico W (which is near-idential to the pico target)
- `thingplus-rp2040`, `waveshare-rp2040-zero`: add WS2812 definition
- `pca10059-s140v7`: add this variant to the PCA10059 board
0.31.2
---
+46 -18
View File
@@ -268,6 +268,11 @@ lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
cd lib/wasi-libc && $(MAKE) -j4 EXTRA_CFLAGS="-O2 -g -DNDEBUG -mnontrapping-fptoint -msign-ext" MALLOC_IMPL=none CC="$(CLANG)" AR=$(LLVM_AR) NM=$(LLVM_NM)
# Generate WASI syscall bindings
.PHONY: wasi-syscall
wasi-syscall:
wit-bindgen-go generate -o ./src/internal -p internal --versioned ./lib/wasi-cli/wit
# Check for Node.js used during WASM tests.
NODEJS_VERSION := $(word 1,$(subst ., ,$(shell node -v | cut -c 2-)))
MIN_NODEJS_VERSION=18
@@ -430,15 +435,36 @@ tinygo-test-wasi:
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
tinygo-test-wasip1:
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
tinygo-test-wasi-fast:
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-test-wasip1-fast:
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-bench-wasi:
$(TINYGO) test -target=wasip1 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-test-wasip2-slow:
$(TINYGO) test -target=wasip2 $(TEST_PACKAGES_SLOW)
tinygo-test-wasip2-fast:
$(TINYGO) test -target=wasip2 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
tinygo-test-wasip2-sum-slow:
TINYGO=$(TINYGO) \
TARGET=wasip2 \
TESTOPTS="-x -work" \
PACKAGES="$(TEST_PACKAGES_SLOW)" \
gotestsum --raw-command -- ./tools/tgtestjson.sh
tinygo-test-wasip2-sum-fast:
TINYGO=$(TINYGO) \
TARGET=wasip2 \
TESTOPTS="-x -work" \
PACKAGES="$(TEST_PACKAGES_FAST)" \
gotestsum --raw-command -- ./tools/tgtestjson.sh
tinygo-bench-wasip1:
$(TINYGO) test -target wasip1 -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
tinygo-bench-wasi-fast:
tinygo-bench-wasip1-fast:
$(TINYGO) test -target wasip1 -bench . $(TEST_PACKAGES_FAST)
tinygo-bench-wasip2:
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
tinygo-bench-wasip2-fast:
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST)
# Test external packages in a large corpus.
test-corpus:
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
@@ -491,7 +517,7 @@ smoketest:
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nano-rp2040 examples/rtcinterrupt
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/serial
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/machinetest
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/systick
@$(MD5SUM) test.hex
@@ -523,7 +549,7 @@ ifneq ($(WASM), 0)
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_bluefruit examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=mch2022 examples/serial
$(TINYGO) build -size short -o test.wasm -tags=mch2022 examples/machinetest
@$(MD5SUM) test.wasm
$(TINYGO) build -size short -o test.wasm -tags=gopher_badge examples/blinky1
@$(MD5SUM) test.wasm
@@ -621,7 +647,7 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=itsybitsy-nrf52840 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=qtpy examples/serial
$(TINYGO) build -size short -o test.hex -target=qtpy examples/machinetest
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=teensy41 examples/blinky1
@$(MD5SUM) test.hex
@@ -693,7 +719,7 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/usb-midi
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nrf52840-s140v6-uf2-generic examples/serial
$(TINYGO) build -size short -o test.hex -target=nrf52840-s140v6-uf2-generic examples/machinetest
@$(MD5SUM) test.hex
ifneq ($(STM32), 0)
$(TINYGO) build -size short -o test.hex -target=bluepill examples/blinky1
@@ -735,7 +761,7 @@ ifneq ($(STM32), 0)
endif
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/machinetest
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1
@$(MD5SUM) test.hex
@@ -762,22 +788,22 @@ ifneq ($(XTENSA), 0)
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=nodemcu examples/blinky1
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target m5stack-core2 examples/serial
$(TINYGO) build -size short -o test.bin -target m5stack-core2 examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target m5stack examples/serial
$(TINYGO) build -size short -o test.bin -target m5stack examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target m5stick-c examples/serial
$(TINYGO) build -size short -o test.bin -target m5stick-c examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target m5paper examples/serial
$(TINYGO) build -size short -o test.bin -target m5paper examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
$(TINYGO) build -size short -o test.bin -target mch2022 examples/machinetest
@$(MD5SUM) test.bin
endif
$(TINYGO) build -size short -o test.bin -target=qtpy-esp32c3 examples/serial
$(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/serial
$(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/serial
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/machinetest
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
@$(MD5SUM) test.hex
@@ -832,6 +858,7 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-bottom-half/headers
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
@mkdir -p build/release/tinygo/lib/wasi-cli/
@mkdir -p build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0
@mkdir -p build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus
@mkdir -p build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4
@@ -891,6 +918,7 @@ endif
@cp -rp lib/wasi-libc/libc-top-half/musl/src/string build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
@cp -rp lib/wasi-libc/libc-top-half/musl/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
@cp -rp lib/wasi-cli/wit build/release/tinygo/lib/wasi-cli/wit
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
@cp -rp src build/release/tinygo/src
+62 -14
View File
@@ -243,7 +243,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
// Create the *ssa.Program. This does not yet build the entire SSA of the
// program so it's pretty fast and doesn't need to be parallelized.
program := lprogram.LoadSSA()
program.Build()
// Add jobs to compile each package.
// Packages that have a cache hit will not be compiled again.
@@ -355,8 +354,8 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
packageActionIDJobs[pkg.ImportPath] = packageActionIDJob
// Build the SSA for the given package.
//ssaPkg := program.Package(pkg.Pkg)
//ssaPkg.Build()
ssaPkg := program.Package(pkg.Pkg)
ssaPkg.Build()
// Now create the job to actually build the package. It will exit early
// if the package is already compiled.
@@ -371,12 +370,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
if _, err := os.Stat(job.result); err == nil {
// Already cached, don't recreate this package.
switch pkg.ImportPath {
case "context": // seems to be needed
case "time": // often crashes in this package, so probably needed
default:
return nil
}
return nil
}
// Compile AST to IR. The compiler.CompilePackage function will
@@ -523,8 +517,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
run: func(*compileJob) error {
// Load and link all the bitcode files. This does not yet optimize
// anything, it only links the bitcode files together.
println("exit")
os.Exit(0)
ctx := llvm.NewContext()
mod = ctx.NewModule("main")
for _, pkgJob := range packageJobs {
@@ -848,11 +840,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
"--output", result.Executable,
)
wasmopt := goenv.Get("WASMOPT")
if config.Options.PrintCommands != nil {
config.Options.PrintCommands(goenv.Get("WASMOPT"), args...)
config.Options.PrintCommands(wasmopt, args...)
}
cmd := exec.Command(goenv.Get("WASMOPT"), args...)
cmd := exec.Command(wasmopt, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@@ -862,6 +854,62 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
}
}
// Run wasm-tools for component-model binaries
witPackage := strings.ReplaceAll(config.Target.WITPackage, "{root}", goenv.Get("TINYGOROOT"))
if config.Options.WITPackage != "" {
witPackage = config.Options.WITPackage
}
witWorld := config.Target.WITWorld
if config.Options.WITWorld != "" {
witWorld = config.Options.WITWorld
}
if witPackage != "" && witWorld != "" {
// wasm-tools component embed -w wasi:cli/command
// $$(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm
args := []string{
"component",
"embed",
"-w", witWorld,
witPackage,
result.Executable,
"-o", result.Executable,
}
wasmtools := goenv.Get("WASMTOOLS")
if config.Options.PrintCommands != nil {
config.Options.PrintCommands(wasmtools, args...)
}
cmd := exec.Command(wasmtools, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return fmt.Errorf("wasm-tools failed: %w", err)
}
// wasm-tools component new embedded.wasm -o component.wasm
args = []string{
"component",
"new",
result.Executable,
"-o", result.Executable,
}
if config.Options.PrintCommands != nil {
config.Options.PrintCommands(wasmtools, args...)
}
cmd = exec.Command(wasmtools, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
return fmt.Errorf("wasm-tools failed: %w", err)
}
}
// Print code size if requested.
if config.Options.PrintSizes == "short" || config.Options.PrintSizes == "full" {
packagePathMap := make(map[string]string, len(lprogram.Packages))
+2
View File
@@ -34,6 +34,7 @@ func TestClangAttributes(t *testing.T) {
"nintendoswitch",
"riscv-qemu",
"wasip1",
"wasip2",
"wasm",
"wasm-unknown",
}
@@ -61,6 +62,7 @@ func TestClangAttributes(t *testing.T) {
{GOOS: "windows", GOARCH: "amd64"},
{GOOS: "windows", GOARCH: "arm64"},
{GOOS: "wasip1", GOARCH: "wasm"},
{GOOS: "wasip2", GOARCH: "wasm"},
} {
name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH
if options.GOARCH == "arm" {
+2 -2
View File
@@ -27,10 +27,10 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
if err != nil {
return nil, err
}
if major != 1 || minor < 18 || minor > 22 {
if major != 1 || minor < 19 || minor > 22 {
// 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.18 through 1.22, got go%d.%d", major, minor)
return nil, fmt.Errorf("requires go version 1.19 through 1.22, got go%d.%d", major, minor)
}
return &compileopts.Config{
+12 -2
View File
@@ -17,6 +17,8 @@ var (
token.OR: precedenceOr,
token.XOR: precedenceXor,
token.AND: precedenceAnd,
token.SHL: precedenceShift,
token.SHR: precedenceShift,
token.ADD: precedenceAdd,
token.SUB: precedenceAdd,
token.MUL: precedenceMul,
@@ -25,11 +27,13 @@ var (
}
)
// See: https://en.cppreference.com/w/c/language/operator_precedence
const (
precedenceLowest = iota + 1
precedenceOr
precedenceXor
precedenceAnd
precedenceShift
precedenceAdd
precedenceMul
precedencePrefix
@@ -82,7 +86,7 @@ func parseConstExpr(t *tokenizer, precedence int) (ast.Expr, *scanner.Error) {
for t.peekToken != token.EOF && precedence < precedences[t.peekToken] {
switch t.peekToken {
case token.OR, token.XOR, token.AND, token.ADD, token.SUB, token.MUL, token.QUO, token.REM:
case token.OR, token.XOR, token.AND, token.SHL, token.SHR, token.ADD, token.SUB, token.MUL, token.QUO, token.REM:
t.Next()
leftExpr, err = parseBinaryExpr(t, leftExpr)
}
@@ -205,13 +209,19 @@ func (t *tokenizer) Next() {
// https://en.cppreference.com/w/cpp/string/byte/isspace
t.peekPos++
t.buf = t.buf[1:]
case len(t.buf) >= 2 && (string(t.buf[:2]) == "||" || string(t.buf[:2]) == "&&"):
case len(t.buf) >= 2 && (string(t.buf[:2]) == "||" || string(t.buf[:2]) == "&&" || string(t.buf[:2]) == "<<" || string(t.buf[:2]) == ">>"):
// Two-character tokens.
switch c {
case '&':
t.peekToken = token.LAND
case '|':
t.peekToken = token.LOR
case '<':
t.peekToken = token.SHL
case '>':
t.peekToken = token.SHR
default:
panic("unreachable")
}
t.peekValue = t.buf[:2]
t.buf = t.buf[2:]
+4
View File
@@ -40,6 +40,10 @@ func TestParseConst(t *testing.T) {
{`5&5`, `5 & 5`},
{`5|5`, `5 | 5`},
{`5^5`, `5 ^ 5`},
{`5<<5`, `5 << 5`},
{`5>>5`, `5 >> 5`},
{`5>>5 + 3`, `5 >> (5 + 3)`},
{`5>>5 ^ 3`, `5>>5 ^ 3`},
{`5||5`, `error: 1:2: unexpected token ||, expected end of expression`}, // logical binops aren't supported yet
{`(5/5)`, `(5 / 5)`},
{`1 - 2`, `1 - 2`},
-7
View File
@@ -642,13 +642,6 @@ func (p *cgoPackage) addErrorAfter(pos token.Pos, after, msg string) {
// addErrorAt is a utility function to add an error to the list of errors.
func (p *cgoPackage) addErrorAt(position token.Position, msg string) {
if filepath.IsAbs(position.Filename) {
// Relative paths for readability, like other Go parser errors.
relpath, err := filepath.Rel(p.currentDir, position.Filename)
if err == nil {
position.Filename = relpath
}
}
p.errors = append(p.errors, scanner.Error{
Pos: position,
Msg: msg,
+2
View File
@@ -53,6 +53,8 @@ type Options struct {
Monitor bool
BaudRate int
Timeout time.Duration
WITPackage string // pass through to wasm-tools component embed invocation
WITWorld string // pass through to wasm-tools component embed -w option
}
// Verify performs a validation on the given options, raising an error if options are not valid.
+2
View File
@@ -62,6 +62,8 @@ type TargetSpec struct {
JLinkDevice string `json:"jlink-device,omitempty"`
CodeModel string `json:"code-model,omitempty"`
RelocationModel string `json:"relocation-model,omitempty"`
WITPackage string `json:"wit-package,omitempty"`
WITWorld string `json:"wit-world,omitempty"`
}
// overrideProperties overrides all properties that are set in child into itself using reflection.
-17
View File
@@ -1,9 +1,6 @@
package compiler
import (
"fmt"
"strings"
"tinygo.org/x/go-llvm"
)
@@ -15,20 +12,6 @@ func (b *builder) createAtomicOp(name string) llvm.Value {
case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
if strings.HasPrefix(b.Triple, "avr") {
// AtomicRMW does not work on AVR as intended:
// - There are some register allocation issues (fixed by https://reviews.llvm.org/D97127 which is not yet in a usable LLVM release)
// - The result is the new value instead of the old value
vType := val.Type()
name := fmt.Sprintf("__sync_fetch_and_add_%d", vType.IntTypeWidth()/8)
fn := b.mod.NamedFunction(name)
if fn.IsNil() {
fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(), vType}, false))
}
oldVal := b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val}, "")
// Return the new value, not the original value returned.
return b.CreateAdd(oldVal, val, "")
}
oldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpAdd, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)
// Return the new value, not the original value returned by atomicrmw.
return b.CreateAdd(oldVal, val, "")
+6 -2
View File
@@ -1846,9 +1846,9 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
return b.emitSV64Call(instr.Args, getPos(instr))
case strings.HasPrefix(name, "(device/riscv.CSR)."):
return b.emitCSROperation(instr)
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"):
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall"):
return b.createSyscall(instr)
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
return b.createRawSyscallNoError(instr)
case name == "runtime.supportsRecover":
supportsRecover := uint64(0)
@@ -2017,6 +2017,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
sizeValue := llvm.ConstInt(b.uintptrType, size, false)
layoutValue := b.createObjectLayout(typ, expr.Pos())
buf := b.createRuntimeCall("alloc", []llvm.Value{sizeValue, layoutValue}, expr.Comment)
align := b.targetData.ABITypeAlignment(typ)
buf.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align)))
return buf, nil
} else {
buf := llvmutil.CreateEntryBlockAlloca(b.Builder, typ, expr.Comment)
@@ -2223,6 +2225,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
sliceType := expr.Type().Underlying().(*types.Slice)
llvmElemType := b.getLLVMType(sliceType.Elem())
elemSize := b.targetData.TypeAllocSize(llvmElemType)
elemAlign := b.targetData.ABITypeAlignment(llvmElemType)
elemSizeValue := llvm.ConstInt(b.uintptrType, elemSize, false)
maxSize := b.maxSliceSize(llvmElemType)
@@ -2246,6 +2249,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
sliceSize := b.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap")
layoutValue := b.createObjectLayout(llvmElemType, expr.Pos())
slicePtr := b.createRuntimeCall("alloc", []llvm.Value{sliceSize, layoutValue}, "makeslice.buf")
slicePtr.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(elemAlign)))
// Extend or truncate if necessary. This is safe as we've already done
// the bounds check.
+1 -2
View File
@@ -514,8 +514,7 @@ var basicTypeNames = [...]string{
func getTypeCodeName(t types.Type) (string, bool) {
switch t := t.(type) {
case *types.Named:
// Note: check for `t.Obj().Pkg() != nil` for Go 1.18 only.
if t.Obj().Pkg() != nil && t.Obj().Parent() != t.Obj().Pkg().Scope() {
if t.Obj().Parent() != t.Obj().Pkg().Scope() {
return "named:" + t.String() + "$local", true
}
return "named:" + t.String(), false
+2
View File
@@ -127,12 +127,14 @@ func (b *builder) emitPointerPack(values []llvm.Value) llvm.Value {
// Packed data is bigger than a pointer, so allocate it on the heap.
sizeValue := llvm.ConstInt(b.uintptrType, size, false)
align := b.targetData.ABITypeAlignment(packedType)
alloc := b.mod.NamedFunction("runtime.alloc")
packedAlloc := b.CreateCall(alloc.GlobalValueType(), alloc, []llvm.Value{
sizeValue,
llvm.ConstNull(b.dataPtrType),
llvm.Undef(b.dataPtrType), // unused context parameter
}, "")
packedAlloc.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align)))
if b.NeedsStackObjects {
b.trackPointer(packedAlloc)
}
+39 -9
View File
@@ -346,7 +346,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
// 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) {
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" {
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
@@ -360,38 +360,68 @@ func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
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(), true) {
if !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(), false) {
if !isValidWasmType(param.Type(), siteParam) {
c.addError(param.Pos(), fmt.Sprintf("%s: unsupported parameter type %s", pragma, param.Type().String()))
}
}
}
// Check whether the type maps directly to a WebAssembly type, according to:
// Check whether the type maps directly to a WebAssembly type.
//
// This reflects the relaxed type restrictions proposed here (except for structs.HostLayout):
// https://github.com/golang/go/issues/66984
//
// This previously reflected the additional restrictions documented here:
// https://github.com/golang/go/issues/59149
func isValidWasmType(typ types.Type, isReturn bool) bool {
func isValidWasmType(typ types.Type, site wasmSite) bool {
switch typ := typ.Underlying().(type) {
case *types.Basic:
switch typ.Kind() {
case types.Int32, types.Uint32, types.Int64, types.Uint64:
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:
return true
case types.Float32, types.Float64:
return true
case types.UnsafePointer:
if !isReturn {
return true
case types.Uintptr, types.UnsafePointer:
return true
case types.String:
// string flattens to two values, so disallowed as a result
return site == siteParam || site == siteIndirect
}
case *types.Array:
return site == siteIndirect && isValidWasmType(typ.Elem(), siteIndirect)
case *types.Struct:
if site != siteIndirect {
return false
}
for i := 0; i < typ.NumFields(); i++ {
if !isValidWasmType(typ.Field(i).Type(), siteIndirect) {
return false
}
}
return true
case *types.Pointer:
return isValidWasmType(typ.Elem(), siteIndirect)
}
return false
}
type wasmSite int
const (
siteParam wasmSite = iota
siteResult
siteIndirect // pointer or field
)
// getParams returns the function parameters, including the receiver at the
// start. This is an alternative to the Params member of *ssa.Function, which is
// not yet populated when the package has not yet been built.
+6 -3
View File
@@ -33,18 +33,17 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
"{r10}",
"{r8}",
"{r9}",
"{r11}",
"{r12}",
"{r13}",
}[i]
llvmValue := b.getValue(arg, getPos(call))
args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type())
}
// rcx and r11 are clobbered by the syscall, so make sure they are not used
constraints += ",~{rcx},~{r11}"
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel, false)
return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "386" && b.GOOS == "linux":
// Sources:
// syscall(2) man page
@@ -71,6 +70,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel, false)
return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "arm" && b.GOOS == "linux":
// Implement the EABI system call convention for Linux.
// Source: syscall(2) man page.
@@ -103,6 +103,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
return b.CreateCall(fnType, target, args, ""), nil
case b.GOARCH == "arm64" && b.GOOS == "linux":
// Source: syscall(2) man page.
args := []llvm.Value{}
@@ -135,6 +136,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false)
return b.CreateCall(fnType, target, args, ""), nil
default:
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
}
@@ -217,6 +219,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
retval = b.CreateInsertValue(retval, syscallResult, 0, "")
retval = b.CreateInsertValue(retval, errResult, 2, "")
return retval, nil
default:
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
}
+48 -14
View File
@@ -13,31 +13,65 @@ func implementation() {
type Uint uint32
//go:wasmimport modulename validparam
func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint)
type S struct {
a [4]uint32
b uintptr
c int
d float32
e float64
}
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type string
//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)
// 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 *int32
// 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()
//
//go:wasmimport modulename invalidparam
func invalidparam(a int, b string, c []byte, d *int32)
func invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func())
//go:wasmimport modulename validreturn
func validreturn() int32
//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
//go:wasmimport modulename validreturn_ptr_string
func validreturn_ptr_string() *string
//go:wasmimport modulename validreturn_ptr_struct
func validreturn_ptr_struct() *S
//go:wasmimport modulename validreturn_unsafe_pointer
func validreturn_unsafe_pointer() unsafe.Pointer
// ERROR: //go:wasmimport modulename manyreturns: too many return values
//
//go:wasmimport modulename manyreturns
func manyreturns() (int32, int32)
// ERROR: //go:wasmimport modulename invalidreturn: unsupported result type int
// ERROR: //go:wasmimport modulename invalidreturn_func: unsupported result type func()
//
//go:wasmimport modulename invalidreturn
func invalidreturn() int
//go:wasmimport modulename invalidreturn_func
func invalidreturn_func() func()
// ERROR: //go:wasmimport modulename invalidUnsafePointerReturn: unsupported result type unsafe.Pointer
// ERROR: //go:wasmimport modulename invalidreturn_slice_byte: unsupported result type []byte
//
//go:wasmimport modulename invalidUnsafePointerReturn
func invalidUnsafePointerReturn() unsafe.Pointer
//go:wasmimport modulename invalidreturn_slice_byte
func invalidreturn_slice_byte() []byte
// ERROR: //go:wasmimport modulename invalidreturn_chan_int: unsupported result type chan int
//
//go:wasmimport modulename invalidreturn_chan_int
func invalidreturn_chan_int() chan int
// ERROR: //go:wasmimport modulename invalidreturn_string: unsupported result type string
//
//go:wasmimport modulename invalidreturn_string
func invalidreturn_string() string
+16 -16
View File
@@ -39,16 +39,16 @@ entry:
define hidden void @main.newScalar(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%new = call dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new, ptr @main.scalar1, align 4
%new1 = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new1, ptr @main.scalar2, align 4
%new2 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new2, ptr @main.scalar3, align 4
%new3 = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new3, ptr @main.scalar4, align 4
ret void
@@ -58,13 +58,13 @@ entry:
define hidden void @main.newArray(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%new = call dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new, ptr @main.array1, align 4
%new1 = call dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new1, ptr @main.array2, align 4
%new2 = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
%new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new2, ptr @main.array3, align 4
ret void
@@ -74,16 +74,16 @@ entry:
define hidden void @main.newStruct(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%new = call ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new, ptr @main.struct1, align 4
%new1 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new1, ptr @main.struct2, align 4
%new2 = call dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3
%new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new2, ptr @main.struct3, align 4
%new3 = call dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3
%new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3
store ptr %new3, ptr @main.struct4, align 4
ret void
@@ -93,7 +93,7 @@ entry:
define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%new = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3
%new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3
ret ptr %new
}
@@ -102,17 +102,17 @@ entry:
define hidden void @main.makeSlice(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%makeslice = call dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3
store ptr %makeslice, ptr @main.slice1, align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 1), align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4
%makeslice1 = call dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
%makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef) #3
store ptr %makeslice1, ptr @main.slice2, align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 1), align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4
%makeslice3 = call dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3
%makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef) #3
store ptr %makeslice3, ptr @main.slice3, align 4
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 1), align 4
@@ -124,7 +124,7 @@ entry:
define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%0 = call dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3
%0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3
store double %v.r, ptr %0, align 8
%.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1
+4 -4
View File
@@ -63,9 +63,9 @@ entry:
; Function Attrs: nounwind
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
entry:
%n = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
store i32 3, ptr %n, align 4
%0 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
store i32 5, ptr %0, align 4
%1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
store ptr %n, ptr %1, align 4
@@ -98,7 +98,7 @@ declare void @runtime.printint32(i32, ptr) #2
; Function Attrs: nounwind
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
entry:
%0 = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
store i32 5, ptr %0, align 4
%1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
store ptr %fn.context, ptr %1, align 4
@@ -148,7 +148,7 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #2
; Function Attrs: nounwind
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
entry:
%0 = call dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
store ptr %itf.value, ptr %0, align 4
%1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1
store ptr @"main$string", ptr %1, align 4
+4 -4
View File
@@ -66,12 +66,12 @@ entry:
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%n = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9
store i32 3, ptr %n, align 4
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef) #9
%0 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
store i32 5, ptr %0, align 4
%1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
@@ -106,7 +106,7 @@ declare void @runtime.printint32(i32, ptr) #1
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%0 = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
store i32 5, ptr %0, align 4
%1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1
@@ -158,7 +158,7 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #1
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%0 = call dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
store ptr %itf.value, ptr %0, align 4
%1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1
+6 -6
View File
@@ -48,7 +48,7 @@ declare void @runtime.lookupPanic(ptr) #1
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%varargs = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3
store i32 1, ptr %varargs, align 4
%0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1
@@ -100,7 +100,7 @@ entry:
br i1 %slice.maxcap, label %slice.throw, label %slice.next
slice.next: ; preds = %entry
%makeslice.buf = call ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%makeslice.buf = call align 1 ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
@@ -123,7 +123,7 @@ entry:
slice.next: ; preds = %entry
%makeslice.cap = shl nuw i32 %len, 1
%makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%makeslice.buf = call align 2 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
@@ -144,7 +144,7 @@ entry:
slice.next: ; preds = %entry
%makeslice.cap = mul i32 %len, 3
%makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%makeslice.buf = call align 1 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
@@ -165,7 +165,7 @@ entry:
slice.next: ; preds = %entry
%makeslice.cap = shl nuw i32 %len, 2
%makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%makeslice.buf = call align 4 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
@@ -216,7 +216,7 @@ declare void @runtime.sliceToArrayPointerPanic(ptr) #1
define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 {
entry:
%stackalloc = alloca i8, align 1
%makeslice = call dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
%makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
+261
View File
@@ -0,0 +1,261 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"fmt"
"sort"
"strings"
)
// A pair is a pair of values tracked for both the x and y side of a diff.
// It is typically a pair of line indexes.
type pair struct{ x, y int }
// Diff returns an anchored diff of the two texts old and new
// in the “unified diff” format. If old and new are identical,
// Diff returns a nil slice (no output).
//
// Unix diff implementations typically look for a diff with
// the smallest number of lines inserted and removed,
// which can in the worst case take time quadratic in the
// number of lines in the texts. As a result, many implementations
// either can be made to run for a long time or cut off the search
// after a predetermined amount of work.
//
// In contrast, this implementation looks for a diff with the
// smallest number of “unique” lines inserted and removed,
// where unique means a line that appears just once in both old and new.
// We call this an “anchored diff” because the unique lines anchor
// the chosen matching regions. An anchored diff is usually clearer
// than a standard diff, because the algorithm does not try to
// reuse unrelated blank lines or closing braces.
// The algorithm also guarantees to run in O(n log n) time
// instead of the standard O(n²) time.
//
// Some systems call this approach a “patience diff,” named for
// the “patience sorting” algorithm, itself named for a solitaire card game.
// We avoid that name for two reasons. First, the name has been used
// for a few different variants of the algorithm, so it is imprecise.
// Second, the name is frequently interpreted as meaning that you have
// to wait longer (to be patient) for the diff, meaning that it is a slower algorithm,
// when in fact the algorithm is faster than the standard one.
func Diff(oldName string, old []byte, newName string, new []byte) []byte {
if bytes.Equal(old, new) {
return nil
}
x := lines(old)
y := lines(new)
// Print diff header.
var out bytes.Buffer
fmt.Fprintf(&out, "diff %s %s\n", oldName, newName)
fmt.Fprintf(&out, "--- %s\n", oldName)
fmt.Fprintf(&out, "+++ %s\n", newName)
// Loop over matches to consider,
// expanding each match to include surrounding lines,
// and then printing diff chunks.
// To avoid setup/teardown cases outside the loop,
// tgs returns a leading {0,0} and trailing {len(x), len(y)} pair
// in the sequence of matches.
var (
done pair // printed up to x[:done.x] and y[:done.y]
chunk pair // start lines of current chunk
count pair // number of lines from each side in current chunk
ctext []string // lines for current chunk
)
for _, m := range tgs(x, y) {
if m.x < done.x {
// Already handled scanning forward from earlier match.
continue
}
// Expand matching lines as far as possible,
// establishing that x[start.x:end.x] == y[start.y:end.y].
// Note that on the first (or last) iteration we may (or definitely do)
// have an empty match: start.x==end.x and start.y==end.y.
start := m
for start.x > done.x && start.y > done.y && x[start.x-1] == y[start.y-1] {
start.x--
start.y--
}
end := m
for end.x < len(x) && end.y < len(y) && x[end.x] == y[end.y] {
end.x++
end.y++
}
// Emit the mismatched lines before start into this chunk.
// (No effect on first sentinel iteration, when start = {0,0}.)
for _, s := range x[done.x:start.x] {
ctext = append(ctext, "-"+s)
count.x++
}
for _, s := range y[done.y:start.y] {
ctext = append(ctext, "+"+s)
count.y++
}
// If we're not at EOF and have too few common lines,
// the chunk includes all the common lines and continues.
const C = 3 // number of context lines
if (end.x < len(x) || end.y < len(y)) &&
(end.x-start.x < C || (len(ctext) > 0 && end.x-start.x < 2*C)) {
for _, s := range x[start.x:end.x] {
ctext = append(ctext, " "+s)
count.x++
count.y++
}
done = end
continue
}
// End chunk with common lines for context.
if len(ctext) > 0 {
n := end.x - start.x
if n > C {
n = C
}
for _, s := range x[start.x : start.x+n] {
ctext = append(ctext, " "+s)
count.x++
count.y++
}
done = pair{start.x + n, start.y + n}
// Format and emit chunk.
// Convert line numbers to 1-indexed.
// Special case: empty file shows up as 0,0 not 1,0.
if count.x > 0 {
chunk.x++
}
if count.y > 0 {
chunk.y++
}
fmt.Fprintf(&out, "@@ -%d,%d +%d,%d @@\n", chunk.x, count.x, chunk.y, count.y)
for _, s := range ctext {
out.WriteString(s)
}
count.x = 0
count.y = 0
ctext = ctext[:0]
}
// If we reached EOF, we're done.
if end.x >= len(x) && end.y >= len(y) {
break
}
// Otherwise start a new chunk.
chunk = pair{end.x - C, end.y - C}
for _, s := range x[chunk.x:end.x] {
ctext = append(ctext, " "+s)
count.x++
count.y++
}
done = end
}
return out.Bytes()
}
// lines returns the lines in the file x, including newlines.
// If the file does not end in a newline, one is supplied
// along with a warning about the missing newline.
func lines(x []byte) []string {
l := strings.SplitAfter(string(x), "\n")
if l[len(l)-1] == "" {
l = l[:len(l)-1]
} else {
// Treat last line as having a message about the missing newline attached,
// using the same text as BSD/GNU diff (including the leading backslash).
l[len(l)-1] += "\n\\ No newline at end of file\n"
}
return l
}
// tgs returns the pairs of indexes of the longest common subsequence
// of unique lines in x and y, where a unique line is one that appears
// once in x and once in y.
//
// The longest common subsequence algorithm is as described in
// Thomas G. Szymanski, “A Special Case of the Maximal Common
// Subsequence Problem,” Princeton TR #170 (January 1975),
// available at https://research.swtch.com/tgs170.pdf.
func tgs(x, y []string) []pair {
// Count the number of times each string appears in a and b.
// We only care about 0, 1, many, counted as 0, -1, -2
// for the x side and 0, -4, -8 for the y side.
// Using negative numbers now lets us distinguish positive line numbers later.
m := make(map[string]int)
for _, s := range x {
if c := m[s]; c > -2 {
m[s] = c - 1
}
}
for _, s := range y {
if c := m[s]; c > -8 {
m[s] = c - 4
}
}
// Now unique strings can be identified by m[s] = -1+-4.
//
// Gather the indexes of those strings in x and y, building:
// xi[i] = increasing indexes of unique strings in x.
// yi[i] = increasing indexes of unique strings in y.
// inv[i] = index j such that x[xi[i]] = y[yi[j]].
var xi, yi, inv []int
for i, s := range y {
if m[s] == -1+-4 {
m[s] = len(yi)
yi = append(yi, i)
}
}
for i, s := range x {
if j, ok := m[s]; ok && j >= 0 {
xi = append(xi, i)
inv = append(inv, j)
}
}
// Apply Algorithm A from Szymanski's paper.
// In those terms, A = J = inv and B = [0, n).
// We add sentinel pairs {0,0}, and {len(x),len(y)}
// to the returned sequence, to help the processing loop.
J := inv
n := len(xi)
T := make([]int, n)
L := make([]int, n)
for i := range T {
T[i] = n + 1
}
for i := 0; i < n; i++ {
k := sort.Search(n, func(k int) bool {
return T[k] >= J[i]
})
T[k] = J[i]
L[i] = k + 1
}
k := 0
for _, v := range L {
if k < v {
k = v
}
}
seq := make([]pair, 2+k)
seq[1+k] = pair{len(x), len(y)} // sentinel at end
lastj := n
for i := n - 1; i >= 0; i-- {
if L[i] == k && J[i] < lastj {
seq[k] = pair{xi[i], yi[J[i]]}
k--
}
}
seq[0] = pair{0, 0} // sentinel at start
return seq
}
+101
View File
@@ -0,0 +1,101 @@
package main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"github.com/tinygo-org/tinygo/compileopts"
)
// Test the error messages of the TinyGo compiler.
func TestErrors(t *testing.T) {
for _, name := range []string{
"cgo",
"multi",
"loader-importcycle",
"loader-invaliddep",
"loader-invalidpackage",
"loader-nopackage",
"syntax",
"types",
} {
t.Run(name, func(t *testing.T) {
testErrorMessages(t, "./testdata/errors/"+name+".go")
})
}
}
func testErrorMessages(t *testing.T, filename string) {
// Parse expected error messages.
expected := readErrorMessages(t, filename)
// Try to build a binary (this should fail with an error).
tmpdir := t.TempDir()
err := Build(filename, tmpdir+"/out", &compileopts.Options{
Target: "wasip1",
Semaphore: sema,
InterpTimeout: 180 * time.Second,
Debug: true,
VerifyIR: true,
Opt: "z",
})
if err == nil {
t.Fatal("expected to get a compiler error")
}
// Get the full ./testdata/errors directory.
wd, absErr := filepath.Abs("testdata/errors")
if absErr != nil {
t.Fatal(absErr)
}
// Write error message out as plain text.
var buf bytes.Buffer
printCompilerError(err, func(v ...interface{}) {
fmt.Fprintln(&buf, v...)
}, wd)
actual := strings.TrimRight(buf.String(), "\n")
// Check whether the error is as expected.
if canonicalizeErrors(actual) != canonicalizeErrors(expected) {
t.Errorf("expected error:\n%s\ngot:\n%s", indentText(expected, "> "), indentText(actual, "> "))
}
}
func canonicalizeErrors(text string) string {
// Fix for Windows: replace all backslashes with forward slashes so that
// paths will be the same as on POSIX systems.
// (It may also change some other backslashes, but since this is only for
// comparing text it should be fine).
if runtime.GOOS == "windows" {
text = strings.ReplaceAll(text, "\\", "/")
}
return text
}
// Indent the given text with a given indentation string.
func indentText(text, indent string) string {
return indent + strings.ReplaceAll(text, "\n", "\n"+indent)
}
// Read "// ERROR:" prefixed messages from the given file.
func readErrorMessages(t *testing.T, file string) string {
data, err := os.ReadFile(file)
if err != nil {
t.Fatal("could not read input file:", err)
}
var errors []string
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "// ERROR: ") {
errors = append(errors, strings.TrimRight(line[len("// ERROR: "):], "\r\n"))
}
}
return strings.Join(errors, "\n")
}
+6 -6
View File
@@ -1,6 +1,6 @@
module github.com/tinygo-org/tinygo
go 1.18
go 1.19
require (
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c
@@ -17,11 +17,11 @@ require (
github.com/mgechev/revive v1.3.7
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
go.bug.st/serial v1.6.0
golang.org/x/net v0.20.0
golang.org/x/sys v0.16.0
golang.org/x/tools v0.17.0
golang.org/x/net v0.26.0
golang.org/x/sys v0.21.0
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504
gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20240518103902-697964f2a9dc
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8
)
require (
@@ -43,5 +43,5 @@ require (
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/afero v1.11.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/text v0.16.0 // indirect
)
+12 -11
View File
@@ -82,9 +82,10 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
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/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=
@@ -92,12 +93,12 @@ golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504 h1:MMsD8mMfluf/578+3wrTn22pjI/Xkzm+gPW47SYfspY=
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
@@ -105,5 +106,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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=
tinygo.org/x/go-llvm v0.0.0-20240518103902-697964f2a9dc h1:TCzibFa4oLu+njEP3fnRUmZ+QQeb8BjtOwctgcjzL0k=
tinygo.org/x/go-llvm v0.0.0-20240518103902-697964f2a9dc/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
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=
+5
View File
@@ -159,6 +159,11 @@ func Get(name string) string {
}
return findWasmOpt()
case "WASMTOOLS":
if path := os.Getenv("WASMTOOLS"); path != "" {
return path
}
return "wasm-tools"
default:
return ""
}
+1 -1
View File
@@ -9,7 +9,7 @@ import (
// Version of TinyGo.
// Update this value before release of new version of software.
const version = "0.32.0-dev"
const version = "0.33.0-dev"
var (
// This variable is set at build time using -ldflags parameters.
Submodule
+1
Submodule lib/wasi-cli added at 6ae8261709
+4
View File
@@ -236,10 +236,12 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"device/": false,
"examples/": false,
"internal/": true,
"internal/binary/": false,
"internal/bytealg/": false,
"internal/fuzz/": false,
"internal/reflectlite/": false,
"internal/task/": false,
"internal/wasi/": false,
"machine/": false,
"net/": true,
"net/http/": false,
@@ -249,6 +251,8 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
"runtime/": false,
"sync/": true,
"testing/": true,
"vendor/": true,
"vendor/github.com/": false,
}
if goMinor >= 19 {
+57 -8
View File
@@ -128,7 +128,7 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
}
// List the dependencies of this package, in raw JSON format.
extraArgs := []string{"-json", "-deps"}
extraArgs := []string{"-json", "-deps", "-e"}
if config.TestConfig.CompileTestBinary {
extraArgs = append(extraArgs, "-test")
}
@@ -149,6 +149,7 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
// Parse the returned json from `go list`.
decoder := json.NewDecoder(buf)
var pkgErrors []error
for {
pkg := &Package{
program: p,
@@ -188,6 +189,12 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
pos.Filename = strings.Join(fields[:len(fields)-1], ":")
pos.Line, _ = strconv.Atoi(fields[len(fields)-1])
}
if abs, err := filepath.Abs(pos.Filename); err == nil {
// Make the path absolute, so that error messages will be
// prettier (it will be turned back into a relative path
// when printing the error).
pos.Filename = abs
}
pos.Filename = p.getOriginalPath(pos.Filename)
}
err := scanner.Error{
@@ -195,10 +202,11 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
Msg: pkg.Error.Err,
}
if len(pkg.Error.ImportStack) != 0 {
return nil, Error{
pkgErrors = append(pkgErrors, Error{
ImportStack: pkg.Error.ImportStack,
Err: err,
}
})
continue
}
return nil, err
}
@@ -241,6 +249,13 @@ func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config)
p.Packages[pkg.ImportPath] = pkg
}
if len(pkgErrors) != 0 {
// TODO: use errors.Join in Go 1.20.
return nil, Errors{
Errs: pkgErrors,
}
}
if config.TestConfig.CompileTestBinary && !strings.HasSuffix(p.sorted[len(p.sorted)-1].ImportPath, ".test") {
// Trying to compile a test binary but there are no test files in this
// package.
@@ -303,18 +318,34 @@ func (p *Program) MainPkg() *Package {
func (p *Program) Parse() error {
// Parse all packages.
// TODO: do this in parallel.
var errors []error
for _, pkg := range p.sorted {
err := pkg.Parse()
if err != nil {
return err
errors = append(errors, err)
}
}
// Typecheck all packages.
for _, pkg := range p.sorted {
if !pkg.isParsed() || !pkg.allImportsChecked() {
if len(errors) == 0 {
// Sanity check.
// If there are no errors, all packages should have been parsed.
panic("unreachable")
}
continue
}
err := pkg.Check()
if err != nil {
return err
errors = append(errors, err)
}
}
if len(errors) != 0 {
// TODO: use errors.Join in Go 1.20.
return Errors{
Errs: errors,
}
}
@@ -339,12 +370,12 @@ func (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) {
return parser.ParseFile(p.program.fset, originalPath, data, mode)
}
// Parse parses and typechecks this package.
// Parse parses this package.
//
// Idempotent.
func (p *Package) Parse() error {
if len(p.Files) != 0 {
return nil // nothing to do (?)
if p.isParsed() {
return nil // nothing to do
}
// Load the AST.
@@ -364,6 +395,24 @@ func (p *Package) Parse() error {
return nil
}
// isParsed returns whether this package has been parsed.
func (p *Package) isParsed() bool {
// Special case: the unsafe package doesn't have files to parse but does
// have p.Pkg set once it is parsed.
return len(p.Files) != 0 || p.Pkg != nil
}
// allImportsChecked returns whether all imports of this package have been
// type-checked.
func (p *Package) allImportsChecked() bool {
for _, dep := range p.Imports {
if p.program.Packages[dep].Pkg == nil {
return false
}
}
return true
}
// Check runs the package through the typechecker. The package must already be
// loaded and all dependencies must have been checked already.
//
+103 -33
View File
@@ -306,16 +306,25 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
// reads any files.
//
// Ex. run --dir=.. --dir=../.. --dir=../../..
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
var dirs []string
switch config.Options.Target {
case "wasip1":
dirs = dirsToModuleRootRel(result.MainDir, result.ModuleRoot)
case "wasip2":
dirs = dirsToModuleRootAbs(result.MainDir, result.ModuleRoot)
default:
return fmt.Errorf("unknown GOOS target: %v", config.Options.Target)
}
args := []string{"run"}
for _, d := range dirs[1:] {
for _, d := range dirs {
args = append(args, "--dir="+d)
}
// The below re-organizes the arguments so that the current
// directory is added last.
args = append(args, "--env=PWD="+cmd.Dir)
args = append(args, cmd.Args[1:]...)
cmd.Args = append(cmd.Args[:1:1], args...)
cmd.Args = args
}
// Run the test.
@@ -356,8 +365,8 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
return passed, err
}
func dirsToModuleRoot(maindir, modroot string) []string {
var dirs = []string{"."}
func dirsToModuleRootRel(maindir, modroot string) []string {
var dirs []string
last := ".."
// strip off path elements until we hit the module root
// adding `..`, `../..`, `../../..` until we're done
@@ -366,6 +375,20 @@ func dirsToModuleRoot(maindir, modroot string) []string {
last = filepath.Join(last, "..")
maindir = filepath.Dir(maindir)
}
dirs = append(dirs, ".")
return dirs
}
func dirsToModuleRootAbs(maindir, modroot string) []string {
var dirs = []string{maindir}
last := filepath.Join(maindir, "..")
// strip off path elements until we hit the module root
// adding `..`, `../..`, `../../..` until we're done
for maindir != modroot {
dirs = append(dirs, last)
last = filepath.Join(last, "..")
maindir = filepath.Dir(maindir)
}
return dirs
}
@@ -785,6 +808,9 @@ func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
// passes command line arguments and evironment variables in a way appropriate
// for the given emulator.
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) (builder.BuildResult, error) {
isSingleFile := strings.HasSuffix(pkgName, ".go")
// Determine whether we're on a system that supports environment variables
// and command line parameters (operating systems, WASI) or not (baremetal,
// WebAssembly in the browser). If we're on a system without an environment,
@@ -818,9 +844,6 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
}
}
} else if config.EmulatorName() == "wasmtime" {
// Wasmtime needs some special flags to pass environment variables
// and allow reading from the current directory.
emuArgs = append(emuArgs, "--dir=.")
for _, v := range environmentVars {
emuArgs = append(emuArgs, "--env", v)
}
@@ -876,7 +899,26 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
if err != nil {
return result, err
}
name = emulator[0]
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
}
emuArgs = append(emuArgs, "--dir="+dir)
emuArgs = append(emuArgs, "--env=PWD="+dir)
}
}
emuArgs = append(emuArgs, emulator[1:]...)
args = append(emuArgs, args...)
}
@@ -1246,10 +1288,9 @@ func usage(command string) {
// try to make the path relative to the current working directory. If any error
// occurs, this error is ignored and the absolute path is returned instead.
func tryToMakePathRelative(dir string) string {
wd, err := os.Getwd()
if err != nil {
return dir
func tryToMakePathRelative(dir, wd string) string {
if wd == "" {
return dir // working directory not found
}
relpath, err := filepath.Rel(wd, dir)
if err != nil {
@@ -1260,28 +1301,25 @@ func tryToMakePathRelative(dir string) string {
// printCompilerError prints compiler errors using the provided logger function
// (similar to fmt.Println).
//
// There is one exception: interp errors may print to stderr unconditionally due
// to limitations in the LLVM bindings.
func printCompilerError(logln func(...interface{}), err error) {
func printCompilerError(err error, logln func(...interface{}), wd string) {
switch err := err.(type) {
case types.Error:
printCompilerError(logln, scanner.Error{
printCompilerError(scanner.Error{
Pos: err.Fset.Position(err.Pos),
Msg: err.Msg,
})
}, logln, wd)
case scanner.Error:
if !strings.HasPrefix(err.Pos.Filename, filepath.Join(goenv.Get("GOROOT"), "src")) && !strings.HasPrefix(err.Pos.Filename, filepath.Join(goenv.Get("TINYGOROOT"), "src")) {
// This file is not from the standard library (either the GOROOT or
// the TINYGOROOT). Make the path relative, for easier reading.
// Ignore any errors in the process (falling back to the absolute
// path).
err.Pos.Filename = tryToMakePathRelative(err.Pos.Filename)
err.Pos.Filename = tryToMakePathRelative(err.Pos.Filename, wd)
}
logln(err)
case scanner.ErrorList:
for _, scannerErr := range err {
printCompilerError(logln, *scannerErr)
printCompilerError(*scannerErr, logln, wd)
}
case *interp.Error:
logln("#", err.ImportPath)
@@ -1297,19 +1335,35 @@ func printCompilerError(logln func(...interface{}), err error) {
}
}
case loader.Errors:
logln("#", err.Pkg.ImportPath)
// Parser errors, typechecking errors, or `go list` errors.
// err.Pkg is nil for `go list` errors.
if err.Pkg != nil {
logln("#", err.Pkg.ImportPath)
}
for _, err := range err.Errs {
printCompilerError(logln, err)
printCompilerError(err, logln, wd)
}
case loader.Error:
logln(err.Err.Error())
logln("package", err.ImportStack[0])
for _, pkgPath := range err.ImportStack[1:] {
logln("\timports", pkgPath)
if err.Err.Pos.Filename != "" {
// Probably a syntax error in a dependency.
printCompilerError(err.Err, logln, wd)
} else {
// Probably an "import cycle not allowed" error.
logln("package", err.ImportStack[0])
for i := 1; i < len(err.ImportStack); i++ {
pkgPath := err.ImportStack[i]
if i == len(err.ImportStack)-1 {
// last package
logln("\timports", pkgPath+": "+err.Err.Error())
} else {
// not the last pacakge
logln("\timports", pkgPath)
}
}
}
case *builder.MultiError:
for _, err := range err.Errs {
printCompilerError(logln, err)
printCompilerError(err, logln, wd)
}
default:
logln("error:", err)
@@ -1317,10 +1371,14 @@ func printCompilerError(logln func(...interface{}), err error) {
}
func handleCompilerError(err error) {
wd, getwdErr := os.Getwd()
if getwdErr != nil {
wd = ""
}
if err != nil {
printCompilerError(func(args ...interface{}) {
printCompilerError(err, func(args ...interface{}) {
fmt.Fprintln(os.Stderr, args...)
}, err)
}, wd)
os.Exit(1)
}
}
@@ -1465,6 +1523,12 @@ func main() {
flag.StringVar(&outpath, "o", "", "output filename")
}
var witPackage, witWorld string
if command == "help" || command == "build" || command == "test" || command == "run" {
flag.StringVar(&witPackage, "wit-package", "", "wit package for wasm component embedding")
flag.StringVar(&witWorld, "wit-world", "", "wit world for wasm component embedding")
}
var testConfig compileopts.TestConfig
if command == "help" || command == "test" {
flag.BoolVar(&testConfig.CompileOnly, "c", false, "compile the test binary but do not run it")
@@ -1544,6 +1608,8 @@ func main() {
Monitor: *monitor,
BaudRate: *baudrate,
Timeout: *timeout,
WITPackage: witPackage,
WITWorld: witWorld,
}
if *printCommands {
options.PrintCommands = printCommand
@@ -1714,9 +1780,13 @@ func main() {
stderr := (*testStderr)(buf)
passed, err := Test(pkgName, stdout, stderr, options, outpath)
if err != nil {
printCompilerError(func(args ...interface{}) {
wd, err := os.Getwd()
if err != nil {
wd = ""
}
printCompilerError(err, func(args ...interface{}) {
fmt.Fprintln(stderr, args...)
}, err)
}, wd)
}
if !passed {
select {
+18 -1
View File
@@ -181,6 +181,10 @@ func TestBuild(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("wasip1", sema), tests, t)
})
t.Run("WASIp2", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("wasip2", sema), tests, t)
})
}
}
@@ -235,6 +239,14 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
default:
}
}
if options.Target == "wasip2" {
switch name {
case "cgo/":
// waisp2 use our own libc; cgo tests fail
continue
}
}
name := name // redefine to avoid race condition
t.Run(name, func(t *testing.T) {
t.Parallel()
@@ -297,6 +309,10 @@ func emuCheck(t *testing.T, options compileopts.Options) {
}
func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
separators := strings.Count(target, "/")
if (separators == 1 || separators == 2) && !strings.HasSuffix(target, ".json") {
return optionsFromOSARCH(target, sema)
}
return compileopts.Options{
// GOOS/GOARCH are only used if target == ""
GOOS: goenv.Get("GOOS"),
@@ -364,7 +380,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
return cmd.Run()
})
if err != nil {
printCompilerError(t.Log, err)
printCompilerError(err, t.Log, "")
t.Fail()
return
}
@@ -393,6 +409,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
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
}
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build darwin || tinygo.wasm
//go:build darwin || wasip1 || wasip2 || wasm
// This implementation of crypto/rand uses the arc4random_buf function
// (available on both MacOS and WASI) to generate random numbers.
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build linux && !baremetal && !wasip1
//go:build linux && !baremetal && !wasip1 && !wasip2
// This implementation of crypto/rand uses the /dev/urandom pseudo-file to
// generate random numbers.
+4
View File
@@ -3,6 +3,10 @@
// tinygo build -size short -o hello-unknown.wasm -target wasm-unknown -gc=leaking -no-debug ./src/examples/hello-wasm-unknown/
package main
// Smoke test: make sure the fmt package can be imported (even if it isn't
// really useful for wasm-unknown).
import _ "os"
var x int32
//go:wasmimport hosted echo_i32
+17
View File
@@ -0,0 +1,17 @@
package main
// This is the same as examples/serial, but it also imports the machine package.
// It is used as a smoke test for the machine package (for boards that don't
// have an on-board LED and therefore can't use examples/blinky1).
import (
_ "machine" // smoke test for the machine package
"time"
)
func main() {
for {
println("hello world!")
time.Sleep(time.Second)
}
}
+32
View File
@@ -0,0 +1,32 @@
// Package binary is a lightweight replacement package for encoding/binary.
package binary
// This file contains small helper functions for working with binary data.
var LittleEndian = littleEndian{}
type littleEndian struct{}
// Encode data like encoding/binary.LittleEndian.Uint16.
func (littleEndian) Uint16(b []byte) uint16 {
return uint16(b[0]) | uint16(b[1])<<8
}
// Store data like binary.LittleEndian.PutUint16.
func (littleEndian) PutUint16(b []byte, v uint16) {
b[0] = byte(v)
b[1] = byte(v >> 8)
}
// Append data like binary.LittleEndian.AppendUint16.
func (littleEndian) AppendUint16(b []byte, v uint16) []byte {
return append(b,
byte(v),
byte(v>>8),
)
}
// Encode data like encoding/binary.LittleEndian.Uint32.
func (littleEndian) Uint32(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
@@ -0,0 +1,6 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package command represents the world "wasi:cli/command@0.2.0".
package command
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,66 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package environment represents the imported interface "wasi:cli/environment@0.2.0".
package environment
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// GetEnvironment represents the imported function "get-environment".
//
// Get the POSIX-style environment variables.
//
// Each environment variable is provided as a pair of string variable names
// and string value.
//
// Morally, these are a value import, but until value imports are available
// in the component model, this import function should return the same
// values each time it is called.
//
// get-environment: func() -> list<tuple<string, string>>
//
//go:nosplit
func GetEnvironment() (result cm.List[[2]string]) {
wasmimport_GetEnvironment(&result)
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.
//
// get-arguments: func() -> list<string>
//
//go:nosplit
func GetArguments() (result cm.List[string]) {
wasmimport_GetArguments(&result)
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
// directory, interpreting `.` as shorthand for this.
//
// initial-cwd: func() -> option<string>
//
//go:nosplit
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])
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,27 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package exit represents the imported interface "wasi:cli/exit@0.2.0".
package exit
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// Exit represents the imported function "exit".
//
// Exit the current instance and any linked instances.
//
// exit: func(status: result)
//
//go:nosplit
func Exit(status cm.BoolResult) {
status0 := cm.BoolToU32(status)
wasmimport_Exit((uint32)(status0))
return
}
//go:wasmimport wasi:cli/exit@0.2.0 exit
//go:noescape
func wasmimport_Exit(status0 uint32)
+3
View File
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,19 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
package run
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// Exports represents the caller-defined exports from "wasi:cli/run@0.2.0".
var Exports struct {
// Run represents the caller-defined, exported function "run".
//
// Run the program.
//
// run: func() -> result
Run func() (result cm.BoolResult)
}
@@ -0,0 +1,18 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package run represents the exported interface "wasi:cli/run@0.2.0".
package run
import (
"github.com/ydnar/wasm-tools-go/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
}
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,26 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package stderr represents the imported interface "wasi:cli/stderr@0.2.0".
package stderr
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/io/v0.2.0/streams"
)
// GetStderr represents the imported function "get-stderr".
//
// get-stderr: func() -> output-stream
//
//go:nosplit
func GetStderr() (result streams.OutputStream) {
result0 := wasmimport_GetStderr()
result = cm.Reinterpret[streams.OutputStream]((uint32)(result0))
return
}
//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr
//go:noescape
func wasmimport_GetStderr() (result0 uint32)
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,26 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package stdin represents the imported interface "wasi:cli/stdin@0.2.0".
package stdin
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/io/v0.2.0/streams"
)
// GetStdin represents the imported function "get-stdin".
//
// get-stdin: func() -> input-stream
//
//go:nosplit
func GetStdin() (result streams.InputStream) {
result0 := wasmimport_GetStdin()
result = cm.Reinterpret[streams.InputStream]((uint32)(result0))
return
}
//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin
//go:noescape
func wasmimport_GetStdin() (result0 uint32)
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,26 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package stdout represents the imported interface "wasi:cli/stdout@0.2.0".
package stdout
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/io/v0.2.0/streams"
)
// GetStdout represents the imported function "get-stdout".
//
// get-stdout: func() -> output-stream
//
//go:nosplit
func GetStdout() (result streams.OutputStream) {
result0 := wasmimport_GetStdout()
result = cm.Reinterpret[streams.OutputStream]((uint32)(result0))
return
}
//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout
//go:noescape
func wasmimport_GetStdout() (result0 uint32)
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,38 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package terminalinput represents the imported interface "wasi:cli/terminal-input@0.2.0".
//
// Terminal input.
//
// In the future, this may include functions for disabling echoing,
// disabling input buffering so that keyboard events are sent through
// immediately, querying supported features, and so on.
package terminalinput
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// TerminalInput represents the imported resource "wasi:cli/terminal-input@0.2.0#terminal-input".
//
// The input side of a terminal.
//
// resource terminal-input
type TerminalInput cm.Resource
// ResourceDrop represents the imported resource-drop for resource "terminal-input".
//
// Drops a resource handle.
//
//go:nosplit
func (self TerminalInput) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,38 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package terminaloutput represents the imported interface "wasi:cli/terminal-output@0.2.0".
//
// Terminal output.
//
// In the future, this may include functions for querying the terminal
// size, being notified of terminal size changes, querying supported
// features, and so on.
package terminaloutput
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// TerminalOutput represents the imported resource "wasi:cli/terminal-output@0.2.0#terminal-output".
//
// The output side of a terminal.
//
// resource terminal-output
type TerminalOutput cm.Resource
// ResourceDrop represents the imported resource-drop for resource "terminal-output".
//
// Drops a resource handle.
//
//go:nosplit
func (self TerminalOutput) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,31 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package terminalstderr represents the imported interface "wasi:cli/terminal-stderr@0.2.0".
//
// An interface providing an optional `terminal-output` for stderr as a
// link-time authority.
package terminalstderr
import (
"github.com/ydnar/wasm-tools-go/cm"
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
)
// GetTerminalStderr represents the imported function "get-terminal-stderr".
//
// If stderr is connected to a terminal, return a `terminal-output` handle
// allowing further interaction with it.
//
// get-terminal-stderr: func() -> option<terminal-output>
//
//go:nosplit
func GetTerminalStderr() (result cm.Option[terminaloutput.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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,31 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package terminalstdin represents the imported interface "wasi:cli/terminal-stdin@0.2.0".
//
// An interface providing an optional `terminal-input` for stdin as a
// link-time authority.
package terminalstdin
import (
"github.com/ydnar/wasm-tools-go/cm"
terminalinput "internal/wasi/cli/v0.2.0/terminal-input"
)
// GetTerminalStdin represents the imported function "get-terminal-stdin".
//
// If stdin is connected to a terminal, return a `terminal-input` handle
// allowing further interaction with it.
//
// get-terminal-stdin: func() -> option<terminal-input>
//
//go:nosplit
func GetTerminalStdin() (result cm.Option[terminalinput.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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,31 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package terminalstdout represents the imported interface "wasi:cli/terminal-stdout@0.2.0".
//
// An interface providing an optional `terminal-output` for stdout as a
// link-time authority.
package terminalstdout
import (
"github.com/ydnar/wasm-tools-go/cm"
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
)
// GetTerminalStdout represents the imported function "get-terminal-stdout".
//
// If stdout is connected to a terminal, return a `terminal-output` handle
// allowing further interaction with it.
//
// get-terminal-stdout: func() -> option<terminal-output>
//
//go:nosplit
func GetTerminalStdout() (result cm.Option[terminaloutput.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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,115 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package monotonicclock represents the imported interface "wasi:clocks/monotonic-clock@0.2.0".
//
// WASI Monotonic Clock is a clock API intended to let users measure elapsed
// time.
//
// It is intended to be portable at least between Unix-family platforms and
// Windows.
//
// A monotonic clock is a clock which has an unspecified initial value, and
// successive reads of the clock will produce non-decreasing values.
//
// It is intended for measuring elapsed time.
package monotonicclock
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/io/v0.2.0/poll"
)
// Instant represents the u64 "wasi:clocks/monotonic-clock@0.2.0#instant".
//
// An instant in time, in nanoseconds. An instant is relative to an
// unspecified initial value, and can only be compared to instances from
// the same monotonic-clock.
//
// type instant = u64
type Instant uint64
// Duration represents the u64 "wasi:clocks/monotonic-clock@0.2.0#duration".
//
// A duration of time, in nanoseconds.
//
// type duration = u64
type Duration uint64
// Now represents the imported function "now".
//
// Read the current value of the clock.
//
// The clock is monotonic, therefore calling this function repeatedly will
// produce a sequence of non-decreasing values.
//
// now: func() -> instant
//
//go:nosplit
func Now() (result Instant) {
result0 := wasmimport_Now()
result = (Instant)((uint64)(result0))
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
// corresponding to a clock tick.
//
// resolution: func() -> duration
//
//go:nosplit
func Resolution() (result Duration) {
result0 := wasmimport_Resolution()
result = (Duration)((uint64)(result0))
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
// occured.
//
// subscribe-instant: func(when: instant) -> pollable
//
//go:nosplit
func SubscribeInstant(when Instant) (result poll.Pollable) {
when0 := (uint64)(when)
result0 := wasmimport_SubscribeInstant((uint64)(when0))
result = cm.Reinterpret[poll.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
// elapsed, starting at the time at which this function was called.
// occured.
//
// subscribe-duration: func(when: duration) -> pollable
//
//go:nosplit
func SubscribeDuration(when Duration) (result poll.Pollable) {
when0 := (uint64)(when)
result0 := wasmimport_SubscribeDuration((uint64)(when0))
result = cm.Reinterpret[poll.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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,80 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package wallclock represents the imported interface "wasi:clocks/wall-clock@0.2.0".
//
// WASI Wall Clock is a clock API intended to let users query the current
// time. The name "wall" makes an analogy to a "clock on the wall", which
// is not necessarily monotonic as it may be reset.
//
// It is intended to be portable at least between Unix-family platforms and
// Windows.
//
// A wall clock is a clock which measures the date and time according to
// some external reference.
//
// External references may be reset, so this clock is not necessarily
// monotonic, making it unsuitable for measuring elapsed time.
//
// It is intended for reporting the current date and time for humans.
package wallclock
// DateTime represents the record "wasi:clocks/wall-clock@0.2.0#datetime".
//
// A time and date in seconds plus nanoseconds.
//
// record datetime {
// seconds: u64,
// nanoseconds: u32,
// }
type DateTime struct {
Seconds uint64
Nanoseconds uint32
}
// Now represents the imported function "now".
//
// Read the current value of the clock.
//
// This clock is not monotonic, therefore calling this function repeatedly
// will not necessarily produce a sequence of non-decreasing values.
//
// The returned timestamps represent the number of seconds since
// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],
// also known as [Unix Time].
//
// The nanoseconds field of the output is always less than 1000000000.
//
// now: func() -> datetime
//
// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16
// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time
//
//go:nosplit
func Now() (result DateTime) {
wasmimport_Now(&result)
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.
//
// The nanoseconds field of the output is always less than 1000000000.
//
// resolution: func() -> datetime
//
//go:nosplit
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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,27 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package preopens represents the imported interface "wasi:filesystem/preopens@0.2.0".
package preopens
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/filesystem/v0.2.0/types"
)
// GetDirectories represents the imported function "get-directories".
//
// Return the set of preopened directories, and their path.
//
// get-directories: func() -> list<tuple<descriptor, string>>
//
//go:nosplit
func GetDirectories() (result cm.List[cm.Tuple[types.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]])
@@ -0,0 +1,53 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
package types
import (
"github.com/ydnar/wasm-tools-go/cm"
wallclock "internal/wasi/clocks/v0.2.0/wall-clock"
"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 {
shape [unsafe.Sizeof(MetadataHashValue{})]byte
}
// TupleListU8BoolShape is used for storage in variant or result types.
type TupleListU8BoolShape struct {
shape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte
}
func lower_DateTime(v wallclock.DateTime) (f0 uint64, f1 uint32) {
f0 = (uint64)(v.Seconds)
f1 = (uint32)(v.Nanoseconds)
return
}
func lower_NewTimestamp(v NewTimestamp) (f0 uint32, f1 uint64, f2 uint32) {
f0 = (uint32)(v.Tag())
switch f0 {
case 2: // timestamp
v1, v2 := lower_DateTime(*v.Timestamp())
f1 = (uint64)(v1)
f2 = (uint32)(v2)
}
return
}
// DescriptorStatShape is used for storage in variant or result types.
type DescriptorStatShape struct {
shape [unsafe.Sizeof(DescriptorStat{})]byte
}
// OptionDirectoryEntryShape is used for storage in variant or result types.
type OptionDirectoryEntryShape struct {
shape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte
}
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,73 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package ioerror represents the imported interface "wasi:io/error@0.2.0".
package ioerror
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// Error represents the imported resource "wasi:io/error@0.2.0#error".
//
// A resource which represents some error information.
//
// The only method provided by this resource is `to-debug-string`,
// which provides some human-readable information about the error.
//
// In the `wasi:io` package, this resource is returned through the
// `wasi:io/streams/stream-error` type.
//
// To provide more specific error information, other interfaces may
// provide functions to further "downcast" this error into more specific
// error information. For example, `error`s returned in streams derived
// from filesystem types to be described using the filesystem's own
// error-code type, using the function
// `wasi:filesystem/types/filesystem-error-code`, which takes a parameter
// `borrow<error>` and returns
// `option<wasi:filesystem/types/error-code>`.
//
// The set of functions which can "downcast" an `error` into a more
// concrete type is open.
//
// resource error
type Error cm.Resource
// ResourceDrop represents the imported resource-drop for resource "error".
//
// Drops a resource handle.
//
//go:nosplit
func (self Error) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_ErrorResourceDrop((uint32)(self0))
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
// this error.
//
// WARNING: The returned string should not be consumed mechanically!
// It may change across platforms, hosts, or other implementation
// details. Parsing this string is a major platform-compatibility
// hazard.
//
// to-debug-string: func() -> string
//
//go:nosplit
func (self Error) ToDebugString() (result string) {
self0 := cm.Reinterpret[uint32](self)
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)
+3
View File
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,110 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package poll represents the imported interface "wasi:io/poll@0.2.0".
//
// A poll API intended to let users wait for I/O events on multiple handles
// at once.
package poll
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// Pollable represents the imported resource "wasi:io/poll@0.2.0#pollable".
//
// `pollable` represents a single I/O event which may be ready, or not.
//
// resource pollable
type Pollable cm.Resource
// ResourceDrop represents the imported resource-drop for resource "pollable".
//
// Drops a resource handle.
//
//go:nosplit
func (self Pollable) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_PollableResourceDrop((uint32)(self0))
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
// blocks until ready.
//
// This function is equivalent to calling `poll.poll` on a list
// containing only this pollable.
//
// block: func()
//
//go:nosplit
func (self Pollable) Block() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_PollableBlock((uint32)(self0))
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.
//
// Returns `true` when the pollable is ready, and `false` otherwise.
//
// ready: func() -> bool
//
//go:nosplit
func (self Pollable) Ready() (result bool) {
self0 := cm.Reinterpret[uint32](self)
result0 := wasmimport_PollableReady((uint32)(self0))
result = cm.U32ToBool((uint32)(result0))
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.
//
// This function takes a list of pollables, which identify I/O sources of
// interest, and waits until one or more of the events is ready for I/O.
//
// The result `list<u32>` contains one or more indices of handles in the
// argument list that is ready for I/O.
//
// If the list contains more elements than can be indexed with a `u32`
// value, this function traps.
//
// A timeout can be implemented by adding a pollable from the
// wasi-clocks API to the list.
//
// This function does not return a `result`; polling in itself does not
// do any I/O so it doesn't fail. If any of the I/O sources identified by
// the pollables has an error, it is indicated by marking the source as
// being reaedy for I/O.
//
// poll: func(in: list<borrow<pollable>>) -> list<u32>
//
//go:nosplit
func Poll(in cm.List[Pollable]) (result cm.List[uint32]) {
in0, in1 := cm.LowerList(in)
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])
@@ -0,0 +1,14 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
package streams
import (
"unsafe"
)
// StreamErrorShape is used for storage in variant or result types.
type StreamErrorShape struct {
shape [unsafe.Sizeof(StreamError{})]byte
}
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,521 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package streams represents the imported interface "wasi:io/streams@0.2.0".
//
// WASI I/O is an I/O abstraction API which is currently focused on providing
// stream types.
//
// In the future, the component model is expected to add built-in stream types;
// when it does, they are expected to subsume this API.
package streams
import (
"github.com/ydnar/wasm-tools-go/cm"
ioerror "internal/wasi/io/v0.2.0/error"
"internal/wasi/io/v0.2.0/poll"
)
// StreamError represents the imported variant "wasi:io/streams@0.2.0#stream-error".
//
// An error for input-stream and output-stream operations.
//
// variant stream-error {
// last-operation-failed(error),
// closed,
// }
type StreamError cm.Variant[uint8, ioerror.Error, ioerror.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 {
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)
}
// StreamErrorClosed returns a [StreamError] of case "closed".
//
// The stream is closed: no more input will be accepted by the
// stream. A closed output-stream will return this error on all
// future operations.
func StreamErrorClosed() StreamError {
var data struct{}
return cm.New[StreamError](1, data)
}
// Closed returns true if [StreamError] represents the variant case "closed".
func (self *StreamError) Closed() bool {
return self.Tag() == 1
}
// InputStream represents the imported resource "wasi:io/streams@0.2.0#input-stream".
//
// An input bytestream.
//
// `input-stream`s are *non-blocking* to the extent practical on underlying
// platforms. I/O operations always return promptly; if fewer bytes are
// promptly available than requested, they return the number of bytes promptly
// available, which could even be zero. To wait for data to be available,
// use the `subscribe` function to obtain a `pollable` which can be polled
// for using `wasi:io/poll`.
//
// resource input-stream
type InputStream cm.Resource
// ResourceDrop represents the imported resource-drop for resource "input-stream".
//
// Drops a resource handle.
//
//go:nosplit
func (self InputStream) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_InputStreamResourceDrop((uint32)(self0))
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
// be read. Except for blocking, behavior is identical to `read`.
//
// blocking-read: func(len: u64) -> result<list<u8>, stream-error>
//
//go:nosplit
func (self InputStream) BlockingRead(len_ uint64) (result cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) {
self0 := cm.Reinterpret[uint32](self)
len0 := (uint64)(len_)
wasmimport_InputStreamBlockingRead((uint32)(self0), (uint64)(len0), &result)
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
// can be skipped. Except for blocking behavior, identical to `skip`.
//
// blocking-skip: func(len: u64) -> result<u64, stream-error>
//
//go:nosplit
func (self InputStream) BlockingSkip(len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
len0 := (uint64)(len_)
wasmimport_InputStreamBlockingSkip((uint32)(self0), (uint64)(len0), &result)
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.
//
// When the source of a `read` is binary data, the bytes from the source
// are returned verbatim. When the source of a `read` is known to the
// implementation to be text, bytes containing the UTF-8 encoding of the
// text are returned.
//
// This function returns a list of bytes containing the read data,
// when successful. The returned list will contain up to `len` bytes;
// it may return fewer than requested, but not more. The list is
// empty when no bytes are available for reading at this time. The
// pollable given by `subscribe` will be ready when more bytes are
// available.
//
// This function fails with a `stream-error` when the operation
// encounters an error, giving `last-operation-failed`, or when the
// stream is closed, giving `closed`.
//
// When the caller gives a `len` of 0, it represents a request to
// read 0 bytes. If the stream is still open, this call should
// succeed and return an empty list, or otherwise fail with `closed`.
//
// The `len` parameter is a `u64`, which could represent a list of u8 which
// is not possible to allocate in wasm32, or not desirable to allocate as
// as a return value by the callee. The callee may return a list of bytes
// less than `len` in size while more bytes are available for reading.
//
// read: func(len: u64) -> result<list<u8>, stream-error>
//
//go:nosplit
func (self InputStream) Read(len_ uint64) (result cm.Result[cm.List[uint8], cm.List[uint8], StreamError]) {
self0 := cm.Reinterpret[uint32](self)
len0 := (uint64)(len_)
wasmimport_InputStreamRead((uint32)(self0), (uint64)(len0), &result)
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.
//
// Behaves identical to `read`, except instead of returning a list
// of bytes, returns the number of bytes consumed from the stream.
//
// skip: func(len: u64) -> result<u64, stream-error>
//
//go:nosplit
func (self InputStream) Skip(len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
len0 := (uint64)(len_)
wasmimport_InputStreamSkip((uint32)(self0), (uint64)(len0), &result)
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
// has bytes available to read or the other end of the stream has been
// closed.
// The created `pollable` is a child resource of the `input-stream`.
// Implementations may trap if the `input-stream` is dropped before
// all derived `pollable`s created with this function are dropped.
//
// subscribe: func() -> pollable
//
//go:nosplit
func (self InputStream) Subscribe() (result poll.Pollable) {
self0 := cm.Reinterpret[uint32](self)
result0 := wasmimport_InputStreamSubscribe((uint32)(self0))
result = cm.Reinterpret[poll.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.
//
// `output-stream`s are *non-blocking* to the extent practical on
// underlying platforms. Except where specified otherwise, I/O operations also
// always return promptly, after the number of bytes that can be written
// promptly, which could even be zero. To wait for the stream to be ready to
// accept data, the `subscribe` function to obtain a `pollable` which can be
// polled for using `wasi:io/poll`.
//
// resource output-stream
type OutputStream cm.Resource
// ResourceDrop represents the imported resource-drop for resource "output-stream".
//
// Drops a resource handle.
//
//go:nosplit
func (self OutputStream) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_OutputStreamResourceDrop((uint32)(self0))
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
// and stream is ready for writing again.
//
// blocking-flush: func() -> result<_, stream-error>
//
//go:nosplit
func (self OutputStream) BlockingFlush() (result cm.Result[StreamError, struct{}, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
wasmimport_OutputStreamBlockingFlush((uint32)(self0), &result)
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.
//
// This is similar to `splice`, except that it blocks until the
// `output-stream` is ready for writing, and the `input-stream`
// is ready for reading, before performing the `splice`.
//
// blocking-splice: func(src: borrow<input-stream>, len: u64) -> result<u64, stream-error>
//
//go:nosplit
func (self OutputStream) BlockingSplice(src InputStream, len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
src0 := cm.Reinterpret[uint32](src)
len0 := (uint64)(len_)
wasmimport_OutputStreamBlockingSplice((uint32)(self0), (uint32)(src0), (uint64)(len0), &result)
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
// until all of these operations are complete, or an error occurs.
//
// This is a convenience wrapper around the use of `check-write`,
// `subscribe`, `write`, and `flush`, and is implemented with the
// following pseudo-code:
//
// let pollable = this.subscribe();
// while !contents.is_empty() {
// // Wait for the stream to become writable
// pollable.block();
// let Ok(n) = this.check-write(); // eliding error handling
// let len = min(n, contents.len());
// let (chunk, rest) = contents.split_at(len);
// this.write(chunk ); // eliding error handling
// contents = rest;
// }
// this.flush();
// // Wait for completion of `flush`
// pollable.block();
// // Check for any errors that arose during `flush`
// let _ = this.check-write(); // eliding error handling
//
// blocking-write-and-flush: func(contents: list<u8>) -> result<_, stream-error>
//
//go:nosplit
func (self OutputStream) BlockingWriteAndFlush(contents cm.List[uint8]) (result cm.Result[StreamError, struct{}, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
contents0, contents1 := cm.LowerList(contents)
wasmimport_OutputStreamBlockingWriteAndFlush((uint32)(self0), (*uint8)(contents0), (uint32)(contents1), &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.
// Block until all of these operations are complete, or an error
// occurs.
//
// This is a convenience wrapper around the use of `check-write`,
// `subscribe`, `write-zeroes`, and `flush`, and is implemented with
// the following pseudo-code:
//
// let pollable = this.subscribe();
// while num_zeroes != 0 {
// // Wait for the stream to become writable
// pollable.block();
// let Ok(n) = this.check-write(); // eliding error handling
// let len = min(n, num_zeroes);
// this.write-zeroes(len); // eliding error handling
// num_zeroes -= len;
// }
// this.flush();
// // Wait for completion of `flush`
// pollable.block();
// // Check for any errors that arose during `flush`
// let _ = this.check-write(); // eliding error handling
//
// blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>
//
//go:nosplit
func (self OutputStream) BlockingWriteZeroesAndFlush(len_ uint64) (result cm.Result[StreamError, struct{}, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
len0 := (uint64)(len_)
wasmimport_OutputStreamBlockingWriteZeroesAndFlush((uint32)(self0), (uint64)(len0), &result)
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.
//
// Returns the number of bytes permitted for the next call to `write`,
// or an error. Calling `write` with more bytes than this function has
// permitted will trap.
//
// When this function returns 0 bytes, the `subscribe` pollable will
// become ready when this function will report at least 1 byte, or an
// error.
//
// check-write: func() -> result<u64, stream-error>
//
//go:nosplit
func (self OutputStream) CheckWrite() (result cm.Result[uint64, uint64, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
wasmimport_OutputStreamCheckWrite((uint32)(self0), &result)
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.
//
// This tells the output-stream that the caller intends any buffered
// output to be flushed. the output which is expected to be flushed
// is all that has been passed to `write` prior to this call.
//
// Upon calling this function, the `output-stream` will not accept any
// writes (`check-write` will return `ok(0)`) until the flush has
// completed. The `subscribe` pollable will become ready when the
// flush has completed and the stream can accept more writes.
//
// flush: func() -> result<_, stream-error>
//
//go:nosplit
func (self OutputStream) Flush() (result cm.Result[StreamError, struct{}, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
wasmimport_OutputStreamFlush((uint32)(self0), &result)
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.
//
// The behavior of splice is equivelant to:
// 1. calling `check-write` on the `output-stream`
// 2. calling `read` on the `input-stream` with the smaller of the
// `check-write` permitted length and the `len` provided to `splice`
// 3. calling `write` on the `output-stream` with that read data.
//
// Any error reported by the call to `check-write`, `read`, or
// `write` ends the splice and reports that error.
//
// This function returns the number of bytes transferred; it may be less
// than `len`.
//
// splice: func(src: borrow<input-stream>, len: u64) -> result<u64, stream-error>
//
//go:nosplit
func (self OutputStream) Splice(src InputStream, len_ uint64) (result cm.Result[uint64, uint64, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
src0 := cm.Reinterpret[uint32](src)
len0 := (uint64)(len_)
wasmimport_OutputStreamSplice((uint32)(self0), (uint32)(src0), (uint64)(len0), &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
// is ready for more writing, or an error has occured. When this
// pollable is ready, `check-write` will return `ok(n)` with n>0, or an
// error.
//
// If the stream is closed, this pollable is always ready immediately.
//
// The created `pollable` is a child resource of the `output-stream`.
// Implementations may trap if the `output-stream` is dropped before
// all derived `pollable`s created with this function are dropped.
//
// subscribe: func() -> pollable
//
//go:nosplit
func (self OutputStream) Subscribe() (result poll.Pollable) {
self0 := cm.Reinterpret[uint32](self)
result0 := wasmimport_OutputStreamSubscribe((uint32)(self0))
result = cm.Reinterpret[poll.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.
//
// When the destination of a `write` is binary data, the bytes from
// `contents` are written verbatim. When the destination of a `write` is
// known to the implementation to be text, the bytes of `contents` are
// transcoded from UTF-8 into the encoding of the destination and then
// written.
//
// Precondition: check-write gave permit of Ok(n) and contents has a
// length of less than or equal to n. Otherwise, this function will trap.
//
// returns Err(closed) without writing if the stream has closed since
// the last call to check-write provided a permit.
//
// write: func(contents: list<u8>) -> result<_, stream-error>
//
//go:nosplit
func (self OutputStream) Write(contents cm.List[uint8]) (result cm.Result[StreamError, struct{}, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
contents0, contents1 := cm.LowerList(contents)
wasmimport_OutputStreamWrite((uint32)(self0), (*uint8)(contents0), (uint32)(contents1), &result)
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.
//
// This should be used precisely like `write` with the exact same
// preconditions (must use check-write first), but instead of
// passing a list of bytes, you simply pass the number of zero-bytes
// that should be written.
//
// write-zeroes: func(len: u64) -> result<_, stream-error>
//
//go:nosplit
func (self OutputStream) WriteZeroes(len_ uint64) (result cm.Result[StreamError, struct{}, StreamError]) {
self0 := cm.Reinterpret[uint32](self)
len0 := (uint64)(len_)
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])
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,43 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package insecureseed represents the imported interface "wasi:random/insecure-seed@0.2.0".
//
// The insecure-seed interface for seeding hash-map DoS resistance.
//
// It is intended to be portable at least between Unix-family platforms and
// Windows.
package insecureseed
// InsecureSeed represents the imported function "insecure-seed".
//
// Return a 128-bit value that may contain a pseudo-random value.
//
// The returned value is not required to be computed from a CSPRNG, and may
// even be entirely deterministic. Host implementations are encouraged to
// provide pseudo-random values to any program exposed to
// attacker-controlled content, to enable DoS protection built into many
// languages' hash-map implementations.
//
// This function is intended to only be called once, by a source language
// to initialize Denial Of Service (DoS) protection in its hash-map
// implementation.
//
// # Expected future evolution
//
// This will likely be changed to a value import, to prevent it from being
// called multiple times and potentially used for purposes other than DoS
// protection.
//
// insecure-seed: func() -> tuple<u64, u64>
//
//go:nosplit
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,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,59 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package insecure represents the imported interface "wasi:random/insecure@0.2.0".
//
// The insecure interface for insecure pseudo-random numbers.
//
// It is intended to be portable at least between Unix-family platforms and
// Windows.
package insecure
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// GetInsecureRandomBytes represents the imported function "get-insecure-random-bytes".
//
// Return `len` insecure pseudo-random bytes.
//
// This function is not cryptographically secure. Do not use it for
// anything related to security.
//
// There are no requirements on the values of the returned bytes, however
// implementations are encouraged to return evenly distributed values with
// a long period.
//
// get-insecure-random-bytes: func(len: u64) -> list<u8>
//
//go:nosplit
func GetInsecureRandomBytes(len_ uint64) (result cm.List[uint8]) {
len0 := (uint64)(len_)
wasmimport_GetInsecureRandomBytes((uint64)(len0), &result)
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.
//
// This function returns the same type of pseudo-random data as
// `get-insecure-random-bytes`, represented as a `u64`.
//
// get-insecure-random-u64: func() -> u64
//
//go:nosplit
func GetInsecureRandomU64() (result uint64) {
result0 := wasmimport_GetInsecureRandomU64()
result = (uint64)((uint64)(result0))
return
}
//go:wasmimport wasi:random/insecure@0.2.0 get-insecure-random-u64
//go:noescape
func wasmimport_GetInsecureRandomU64() (result0 uint64)
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,63 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package random represents the imported interface "wasi:random/random@0.2.0".
//
// WASI Random is a random data API.
//
// It is intended to be portable at least between Unix-family platforms and
// Windows.
package random
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// GetRandomBytes represents the imported function "get-random-bytes".
//
// Return `len` cryptographically-secure random or pseudo-random bytes.
//
// This function must produce data at least as cryptographically secure and
// fast as an adequately seeded cryptographically-secure pseudo-random
// number generator (CSPRNG). It must not block, from the perspective of
// the calling program, under any circumstances, including on the first
// request and on requests for numbers of bytes. The returned data must
// always be unpredictable.
//
// This function must always return fresh data. Deterministic environments
// must omit this function, rather than implementing it with deterministic
// data.
//
// get-random-bytes: func(len: u64) -> list<u8>
//
//go:nosplit
func GetRandomBytes(len_ uint64) (result cm.List[uint8]) {
len0 := (uint64)(len_)
wasmimport_GetRandomBytes((uint64)(len0), &result)
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.
//
// This function returns the same type of data as `get-random-bytes`,
// represented as a `u64`.
//
// get-random-u64: func() -> u64
//
//go:nosplit
func GetRandomU64() (result uint64) {
result0 := wasmimport_GetRandomU64()
result = (uint64)((uint64)(result0))
return
}
//go:wasmimport wasi:random/random@0.2.0 get-random-u64
//go:noescape
func wasmimport_GetRandomU64() (result0 uint64)
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,30 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package instancenetwork represents the imported interface "wasi:sockets/instance-network@0.2.0".
//
// This interface provides a value-export of the default network handle..
package instancenetwork
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/sockets/v0.2.0/network"
)
// InstanceNetwork represents the imported function "instance-network".
//
// Get a handle to the default network.
//
// instance-network: func() -> network
//
//go:nosplit
func InstanceNetwork() (result network.Network) {
result0 := wasmimport_InstanceNetwork()
result = cm.Reinterpret[network.Network]((uint32)(result0))
return
}
//go:wasmimport wasi:sockets/instance-network@0.2.0 instance-network
//go:noescape
func wasmimport_InstanceNetwork() (result0 uint32)
@@ -0,0 +1,16 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
package ipnamelookup
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/sockets/v0.2.0/network"
"unsafe"
)
// OptionIPAddressShape is used for storage in variant or result types.
type OptionIPAddressShape struct {
shape [unsafe.Sizeof(cm.Option[network.IPAddress]{})]byte
}
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,123 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package ipnamelookup represents the imported interface "wasi:sockets/ip-name-lookup@0.2.0".
package ipnamelookup
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/io/v0.2.0/poll"
"internal/wasi/sockets/v0.2.0/network"
)
// ResolveAddressStream represents the imported resource "wasi:sockets/ip-name-lookup@0.2.0#resolve-address-stream".
//
// resource resolve-address-stream
type ResolveAddressStream cm.Resource
// ResourceDrop represents the imported resource-drop for resource "resolve-address-stream".
//
// Drops a resource handle.
//
//go:nosplit
func (self ResolveAddressStream) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_ResolveAddressStreamResourceDrop((uint32)(self0))
return
}
//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [resource-drop]resolve-address-stream
//go:noescape
func wasmimport_ResolveAddressStreamResourceDrop(self0 uint32)
// ResolveNextAddress represents the imported method "resolve-next-address".
//
// Returns the next address from the resolver.
//
// This function should be called multiple times. On each call, it will
// return the next address in connection order preference. If all
// addresses have been exhausted, this function returns `none`.
//
// This function never returns IPv4-mapped IPv6 addresses.
//
// # Typical errors
// - `name-unresolvable`: Name does not exist or has no suitable associated
// IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY)
// - `temporary-resolver-failure`: A temporary failure in name resolution occurred.
// (EAI_AGAIN)
// - `permanent-resolver-failure`: A permanent failure in name resolution occurred.
// (EAI_FAIL)
// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN)
//
// resolve-next-address: func() -> result<option<ip-address>, error-code>
//
//go:nosplit
func (self ResolveAddressStream) ResolveNextAddress() (result cm.Result[OptionIPAddressShape, cm.Option[network.IPAddress], network.ErrorCode]) {
self0 := cm.Reinterpret[uint32](self)
wasmimport_ResolveAddressStreamResolveNextAddress((uint32)(self0), &result)
return
}
//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.resolve-next-address
//go:noescape
func wasmimport_ResolveAddressStreamResolveNextAddress(self0 uint32, result *cm.Result[OptionIPAddressShape, cm.Option[network.IPAddress], network.ErrorCode])
// Subscribe represents the imported method "subscribe".
//
// Create a `pollable` which will resolve once the stream is ready for I/O.
//
// Note: this function is here for WASI Preview2 only.
// It's planned to be removed when `future` is natively supported in Preview3.
//
// subscribe: func() -> pollable
//
//go:nosplit
func (self ResolveAddressStream) Subscribe() (result poll.Pollable) {
self0 := cm.Reinterpret[uint32](self)
result0 := wasmimport_ResolveAddressStreamSubscribe((uint32)(self0))
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
return
}
//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 [method]resolve-address-stream.subscribe
//go:noescape
func wasmimport_ResolveAddressStreamSubscribe(self0 uint32) (result0 uint32)
// ResolveAddresses represents the imported function "resolve-addresses".
//
// Resolve an internet host name to a list of IP addresses.
//
// Unicode domain names are automatically converted to ASCII using IDNA encoding.
// If the input is an IP address string, the address is parsed and returned
// as-is without making any external requests.
//
// See the wasi-socket proposal README.md for a comparison with getaddrinfo.
//
// This function never blocks. It either immediately fails or immediately
// returns successfully with a `resolve-address-stream` that can be used
// to (asynchronously) fetch the results.
//
// # Typical errors
// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address.
//
// # References:
// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html>
// - <https://man7.org/linux/man-pages/man3/getaddrinfo.3.html>
// - <https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo>
// - <https://man.freebsd.org/cgi/man.cgi?query=getaddrinfo&sektion=3>
//
// resolve-addresses: func(network: borrow<network>, name: string) -> result<resolve-address-stream,
// error-code>
//
//go:nosplit
func ResolveAddresses(network_ network.Network, name string) (result cm.Result[ResolveAddressStream, ResolveAddressStream, network.ErrorCode]) {
network0 := cm.Reinterpret[uint32](network_)
name0, name1 := cm.LowerString(name)
wasmimport_ResolveAddresses((uint32)(network0), (*uint8)(name0), (uint32)(name1), &result)
return
}
//go:wasmimport wasi:sockets/ip-name-lookup@0.2.0 resolve-addresses
//go:noescape
func wasmimport_ResolveAddresses(network0 uint32, name0 *uint8, name1 uint32, result *cm.Result[ResolveAddressStream, ResolveAddressStream, network.ErrorCode])
@@ -0,0 +1,14 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
package network
import (
"unsafe"
)
// IPv6SocketAddressShape is used for storage in variant or result types.
type IPv6SocketAddressShape struct {
shape [unsafe.Sizeof(IPv6SocketAddress{})]byte
}
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,317 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package network represents the imported interface "wasi:sockets/network@0.2.0".
package network
import (
"github.com/ydnar/wasm-tools-go/cm"
)
// Network represents the imported resource "wasi:sockets/network@0.2.0#network".
//
// An opaque resource that represents access to (a subset of) the network.
// This enables context-based security for networking.
// There is no need for this to map 1:1 to a physical network interface.
//
// resource network
type Network cm.Resource
// ResourceDrop represents the imported resource-drop for resource "network".
//
// Drops a resource handle.
//
//go:nosplit
func (self Network) ResourceDrop() {
self0 := cm.Reinterpret[uint32](self)
wasmimport_NetworkResourceDrop((uint32)(self0))
return
}
//go:wasmimport wasi:sockets/network@0.2.0 [resource-drop]network
//go:noescape
func wasmimport_NetworkResourceDrop(self0 uint32)
// ErrorCode represents the enum "wasi:sockets/network@0.2.0#error-code".
//
// Error codes.
//
// In theory, every API can return any error code.
// In practice, API's typically only return the errors documented per API
// combined with a couple of errors that are always possible:
// - `unknown`
// - `access-denied`
// - `not-supported`
// - `out-of-memory`
// - `concurrency-conflict`
//
// See each individual API for what the POSIX equivalents are. They sometimes differ
// per API.
//
// enum error-code {
// unknown,
// access-denied,
// not-supported,
// invalid-argument,
// out-of-memory,
// timeout,
// concurrency-conflict,
// not-in-progress,
// would-block,
// invalid-state,
// new-socket-limit,
// address-not-bindable,
// address-in-use,
// remote-unreachable,
// connection-refused,
// connection-reset,
// connection-aborted,
// datagram-too-large,
// name-unresolvable,
// temporary-resolver-failure,
// permanent-resolver-failure
// }
type ErrorCode uint8
const (
// Unknown error
ErrorCodeUnknown ErrorCode = iota
// Access denied.
//
// POSIX equivalent: EACCES, EPERM
ErrorCodeAccessDenied
// The operation is not supported.
//
// POSIX equivalent: EOPNOTSUPP
ErrorCodeNotSupported
// One of the arguments is invalid.
//
// POSIX equivalent: EINVAL
ErrorCodeInvalidArgument
// Not enough memory to complete the operation.
//
// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY
ErrorCodeOutOfMemory
// The operation timed out before it could finish completely.
ErrorCodeTimeout
// This operation is incompatible with another asynchronous operation that is already
// in progress.
//
// POSIX equivalent: EALREADY
ErrorCodeConcurrencyConflict
// Trying to finish an asynchronous operation that:
// - has not been started yet, or:
// - was already finished by a previous `finish-*` call.
//
// Note: this is scheduled to be removed when `future`s are natively supported.
ErrorCodeNotInProgress
// The operation has been aborted because it could not be completed immediately.
//
// Note: this is scheduled to be removed when `future`s are natively supported.
ErrorCodeWouldBlock
// The operation is not valid in the socket's current state.
ErrorCodeInvalidState
// A new socket resource could not be created because of a system limit.
ErrorCodeNewSocketLimit
// A bind operation failed because the provided address is not an address that the
// `network` can bind to.
ErrorCodeAddressNotBindable
// A bind operation failed because the provided address is already in use or because
// there are no ephemeral ports available.
ErrorCodeAddressInUse
// The remote address is not reachable
ErrorCodeRemoteUnreachable
// The TCP connection was forcefully rejected
ErrorCodeConnectionRefused
// The TCP connection was reset.
ErrorCodeConnectionReset
// A TCP connection was aborted.
ErrorCodeConnectionAborted
// The size of a datagram sent to a UDP socket exceeded the maximum
// supported size.
ErrorCodeDatagramTooLarge
// Name does not exist or has no suitable associated IP addresses.
ErrorCodeNameUnresolvable
// A temporary failure in name resolution occurred.
ErrorCodeTemporaryResolverFailure
// A permanent failure in name resolution occurred.
ErrorCodePermanentResolverFailure
)
var stringsErrorCode = [21]string{
"unknown",
"access-denied",
"not-supported",
"invalid-argument",
"out-of-memory",
"timeout",
"concurrency-conflict",
"not-in-progress",
"would-block",
"invalid-state",
"new-socket-limit",
"address-not-bindable",
"address-in-use",
"remote-unreachable",
"connection-refused",
"connection-reset",
"connection-aborted",
"datagram-too-large",
"name-unresolvable",
"temporary-resolver-failure",
"permanent-resolver-failure",
}
// String implements [fmt.Stringer], returning the enum case name of e.
func (e ErrorCode) String() string {
return stringsErrorCode[e]
}
// IPAddressFamily represents the enum "wasi:sockets/network@0.2.0#ip-address-family".
//
// enum ip-address-family {
// ipv4,
// ipv6
// }
type IPAddressFamily uint8
const (
// Similar to `AF_INET` in POSIX.
IPAddressFamilyIPv4 IPAddressFamily = iota
// Similar to `AF_INET6` in POSIX.
IPAddressFamilyIPv6
)
var stringsIPAddressFamily = [2]string{
"ipv4",
"ipv6",
}
// String implements [fmt.Stringer], returning the enum case name of e.
func (e IPAddressFamily) String() string {
return stringsIPAddressFamily[e]
}
// IPv4Address represents the tuple "wasi:sockets/network@0.2.0#ipv4-address".
//
// type ipv4-address = tuple<u8, u8, u8, u8>
type IPv4Address [4]uint8
// IPv6Address represents the tuple "wasi:sockets/network@0.2.0#ipv6-address".
//
// type ipv6-address = tuple<u16, u16, u16, u16, u16, u16, u16, u16>
type IPv6Address [8]uint16
// IPAddress represents the variant "wasi:sockets/network@0.2.0#ip-address".
//
// variant ip-address {
// ipv4(ipv4-address),
// ipv6(ipv6-address),
// }
type IPAddress cm.Variant[uint8, IPv6Address, IPv6Address]
// IPAddressIPv4 returns a [IPAddress] of case "ipv4".
func IPAddressIPv4(data IPv4Address) IPAddress {
return cm.New[IPAddress](0, data)
}
// IPv4 returns a non-nil *[IPv4Address] if [IPAddress] represents the variant case "ipv4".
func (self *IPAddress) IPv4() *IPv4Address {
return cm.Case[IPv4Address](self, 0)
}
// IPAddressIPv6 returns a [IPAddress] of case "ipv6".
func IPAddressIPv6(data IPv6Address) IPAddress {
return cm.New[IPAddress](1, data)
}
// IPv6 returns a non-nil *[IPv6Address] if [IPAddress] represents the variant case "ipv6".
func (self *IPAddress) IPv6() *IPv6Address {
return cm.Case[IPv6Address](self, 1)
}
// IPv4SocketAddress represents the record "wasi:sockets/network@0.2.0#ipv4-socket-address".
//
// record ipv4-socket-address {
// port: u16,
// address: ipv4-address,
// }
type IPv4SocketAddress struct {
// sin_port
Port uint16
// sin_addr
Address IPv4Address
}
// IPv6SocketAddress represents the record "wasi:sockets/network@0.2.0#ipv6-socket-address".
//
// record ipv6-socket-address {
// port: u16,
// flow-info: u32,
// address: ipv6-address,
// scope-id: u32,
// }
type IPv6SocketAddress struct {
// sin6_port
Port uint16
// sin6_flowinfo
FlowInfo uint32
// sin6_addr
Address IPv6Address
// sin6_scope_id
ScopeID uint32
}
// IPSocketAddress represents the variant "wasi:sockets/network@0.2.0#ip-socket-address".
//
// variant ip-socket-address {
// ipv4(ipv4-socket-address),
// ipv6(ipv6-socket-address),
// }
type IPSocketAddress cm.Variant[uint8, IPv6SocketAddressShape, IPv6SocketAddress]
// IPSocketAddressIPv4 returns a [IPSocketAddress] of case "ipv4".
func IPSocketAddressIPv4(data IPv4SocketAddress) IPSocketAddress {
return cm.New[IPSocketAddress](0, data)
}
// IPv4 returns a non-nil *[IPv4SocketAddress] if [IPSocketAddress] represents the variant case "ipv4".
func (self *IPSocketAddress) IPv4() *IPv4SocketAddress {
return cm.Case[IPv4SocketAddress](self, 0)
}
// IPSocketAddressIPv6 returns a [IPSocketAddress] of case "ipv6".
func IPSocketAddressIPv6(data IPv6SocketAddress) IPSocketAddress {
return cm.New[IPSocketAddress](1, data)
}
// IPv6 returns a non-nil *[IPv6SocketAddress] if [IPSocketAddress] represents the variant case "ipv6".
func (self *IPSocketAddress) IPv6() *IPv6SocketAddress {
return cm.Case[IPv6SocketAddress](self, 1)
}
@@ -0,0 +1,3 @@
// This file exists for testing this package without WebAssembly,
// allowing empty function bodies with a //go:wasmimport directive.
// See https://pkg.go.dev/cmd/compile for more information.
@@ -0,0 +1,54 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
// Package tcpcreatesocket represents the imported interface "wasi:sockets/tcp-create-socket@0.2.0".
package tcpcreatesocket
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/sockets/v0.2.0/network"
"internal/wasi/sockets/v0.2.0/tcp"
)
// CreateTCPSocket represents the imported function "create-tcp-socket".
//
// Create a new TCP socket.
//
// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX.
// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise.
//
// This function does not require a network capability handle. This is considered
// to be safe because
// at time of creation, the socket is not bound to any `network` yet. Up to the moment
// `bind`/`connect`
// is called, the socket is effectively an in-memory configuration object, unable
// to communicate with the outside world.
//
// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous
// operations.
//
// # Typical errors
// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT)
// - `new-socket-limit`: The new socket resource could not be created because of
// a system limit. (EMFILE, ENFILE)
//
// # References
// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html>
// - <https://man7.org/linux/man-pages/man2/socket.2.html>
// - <https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketw>
// - <https://man.freebsd.org/cgi/man.cgi?query=socket&sektion=2>
//
// create-tcp-socket: func(address-family: ip-address-family) -> result<tcp-socket,
// error-code>
//
//go:nosplit
func CreateTCPSocket(addressFamily network.IPAddressFamily) (result cm.Result[tcp.TCPSocket, tcp.TCPSocket, network.ErrorCode]) {
addressFamily0 := (uint32)(addressFamily)
wasmimport_CreateTCPSocket((uint32)(addressFamily0), &result)
return
}
//go:wasmimport wasi:sockets/tcp-create-socket@0.2.0 create-tcp-socket
//go:noescape
func wasmimport_CreateTCPSocket(addressFamily0 uint32, result *cm.Result[tcp.TCPSocket, tcp.TCPSocket, network.ErrorCode])
@@ -0,0 +1,88 @@
// Code generated by wit-bindgen-go. DO NOT EDIT.
//go:build !wasip1
package tcp
import (
"github.com/ydnar/wasm-tools-go/cm"
"internal/wasi/io/v0.2.0/streams"
"internal/wasi/sockets/v0.2.0/network"
"unsafe"
)
// TupleTCPSocketInputStreamOutputStreamShape is used for storage in variant or result types.
type TupleTCPSocketInputStreamOutputStreamShape struct {
shape [unsafe.Sizeof(cm.Tuple3[TCPSocket, streams.InputStream, streams.OutputStream]{})]byte
}
// TupleInputStreamOutputStreamShape is used for storage in variant or result types.
type TupleInputStreamOutputStreamShape struct {
shape [unsafe.Sizeof(cm.Tuple[streams.InputStream, streams.OutputStream]{})]byte
}
// IPSocketAddressShape is used for storage in variant or result types.
type IPSocketAddressShape struct {
shape [unsafe.Sizeof(network.IPSocketAddress{})]byte
}
func lower_IPv4Address(v network.IPv4Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32) {
f0 = (uint32)(v[0])
f1 = (uint32)(v[1])
f2 = (uint32)(v[2])
f3 = (uint32)(v[3])
return
}
func lower_IPv4SocketAddress(v network.IPv4SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32) {
f0 = (uint32)(v.Port)
f1, f2, f3, f4 = lower_IPv4Address(v.Address)
return
}
func lower_IPv6Address(v network.IPv6Address) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32) {
f0 = (uint32)(v[0])
f1 = (uint32)(v[1])
f2 = (uint32)(v[2])
f3 = (uint32)(v[3])
f4 = (uint32)(v[4])
f5 = (uint32)(v[5])
f6 = (uint32)(v[6])
f7 = (uint32)(v[7])
return
}
func lower_IPv6SocketAddress(v network.IPv6SocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32) {
f0 = (uint32)(v.Port)
f1 = (uint32)(v.FlowInfo)
f2, f3, f4, f5, f6, f7, f8, f9 = lower_IPv6Address(v.Address)
f10 = (uint32)(v.ScopeID)
return
}
func lower_IPSocketAddress(v network.IPSocketAddress) (f0 uint32, f1 uint32, f2 uint32, f3 uint32, f4 uint32, f5 uint32, f6 uint32, f7 uint32, f8 uint32, f9 uint32, f10 uint32, f11 uint32) {
f0 = (uint32)(v.Tag())
switch f0 {
case 0: // ipv4
v1, v2, v3, v4, v5 := lower_IPv4SocketAddress(*v.IPv4())
f1 = (uint32)(v1)
f2 = (uint32)(v2)
f3 = (uint32)(v3)
f4 = (uint32)(v4)
f5 = (uint32)(v5)
case 1: // ipv6
v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 := lower_IPv6SocketAddress(*v.IPv6())
f1 = (uint32)(v1)
f2 = (uint32)(v2)
f3 = (uint32)(v3)
f4 = (uint32)(v4)
f5 = (uint32)(v5)
f6 = (uint32)(v6)
f7 = (uint32)(v7)
f8 = (uint32)(v8)
f9 = (uint32)(v9)
f10 = (uint32)(v10)
f11 = (uint32)(v11)
}
return
}

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