mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-27 07:08:42 +00:00
Compare commits
98 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 587ad68bd9 | |||
| a6602dc708 | |||
| 3de78fcdc6 | |||
| 3610c93b9e | |||
| ac396708da | |||
| d150badf33 | |||
| 2d85fc6a64 | |||
| 5ca3e4a2da | |||
| e6caa3fe9e | |||
| 571447c7c1 | |||
| 9cb263479c | |||
| f18c6e342f | |||
| 2d5a8d407b | |||
| 36958b2875 | |||
| fae0402fde | |||
| 4517a0c17b | |||
| 6abaee4640 | |||
| 1270a50104 | |||
| 868262f4a7 | |||
| d33ace7b59 | |||
| dd6fa89aa6 | |||
| d513cae5d2 | |||
| e612f7cf3f | |||
| 385a7920e6 | |||
| 077b35e9ad | |||
| 880e940417 | |||
| ad6c89bf64 | |||
| ae6220262a | |||
| e731a31eb9 | |||
| 3023ba584b | |||
| 3a8ef33c72 | |||
| 20b58a0128 | |||
| bfccf3592a | |||
| 272fea13e7 | |||
| b6fd0c818e | |||
| c383a407e3 | |||
| 7b7601d77c | |||
| f7c0466f78 | |||
| 81ce7fb738 | |||
| c2776dcf78 | |||
| ad0340d437 | |||
| 30c4df16f2 | |||
| fe27b674cd | |||
| c78dbcd3f2 | |||
| 8890b57ba0 | |||
| ee3a05f1de | |||
| 9307204111 | |||
| 71878c2c0c | |||
| cef2a82c97 | |||
| 1d9f26cee1 | |||
| 6e58c44390 | |||
| 7d6b667bba | |||
| 72f30ca6ec | |||
| 293b620faf | |||
| ad0af607ef | |||
| da23cdeae4 | |||
| d419cc11bf | |||
| 441dfc98d7 | |||
| 2b3b870bfe | |||
| 7748c4922e | |||
| 50f700ddb5 | |||
| f986ea84ac | |||
| 797a5a2031 | |||
| 3d433fe9f1 | |||
| 1154212c15 | |||
| 22bf045c9a | |||
| 39029cc376 | |||
| 7122755725 | |||
| dcee228c4e | |||
| 9d6e30701b | |||
| 85b59e66da | |||
| 90b0bf646c | |||
| c55ac9f28e | |||
| 2733e376bd | |||
| 331cfb65b7 | |||
| 055950421a | |||
| cfcc894855 | |||
| 8bd0155c51 | |||
| 32a056c32a | |||
| 8e8ad9004f | |||
| 62d8cdb218 | |||
| b6fdbee14e | |||
| a5ceb793be | |||
| 7c546525ea | |||
| d628e3e2cb | |||
| d97e4dbccf | |||
| a7ddb33bea | |||
| 8a93196f1f | |||
| 6714974aba | |||
| d67ec3b266 | |||
| 78775007fa | |||
| ad4d722f54 | |||
| 6384ecace0 | |||
| 38881a2850 | |||
| 0f1cf14743 | |||
| 7c34f7704e | |||
| 377415a6c3 | |||
| 1e13c6d18f |
+13
-13
@@ -5,17 +5,17 @@ commands:
|
||||
steps:
|
||||
- run:
|
||||
name: "Pull submodules"
|
||||
command: git submodule update --init --recursive
|
||||
command: git submodule update --init
|
||||
llvm-source-linux:
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- llvm-source-17-v1
|
||||
- llvm-source-18-v1
|
||||
- run:
|
||||
name: "Fetch LLVM source"
|
||||
command: make llvm-source
|
||||
- save_cache:
|
||||
key: llvm-source-17-v1
|
||||
key: llvm-source-18-v1
|
||||
paths:
|
||||
- llvm-project/clang/lib/Headers
|
||||
- llvm-project/clang/include
|
||||
@@ -33,13 +33,13 @@ commands:
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- binaryen-linux-v2
|
||||
- binaryen-linux-v3
|
||||
- run:
|
||||
name: "Build Binaryen"
|
||||
command: |
|
||||
make binaryen
|
||||
- save_cache:
|
||||
key: binaryen-linux-v2
|
||||
key: binaryen-linux-v3
|
||||
paths:
|
||||
- build/wasm-opt
|
||||
test-linux:
|
||||
@@ -88,7 +88,7 @@ commands:
|
||||
# Do this before gen-device so that it doesn't check the
|
||||
# formatting of generated files.
|
||||
name: Check Go code formatting
|
||||
command: make fmt-check
|
||||
command: make fmt-check lint
|
||||
- run: make gen-device -j4
|
||||
- run: make smoketest XTENSA=0
|
||||
- save_cache:
|
||||
@@ -98,19 +98,19 @@ 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"
|
||||
resource_class: large
|
||||
test-llvm17-go122:
|
||||
test-llvm18-go122:
|
||||
docker:
|
||||
- image: golang:1.22-bullseye
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "17"
|
||||
llvm: "18"
|
||||
resource_class: large
|
||||
|
||||
workflows:
|
||||
@@ -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
|
||||
# This tests LLVM 17 support when linking against system libraries.
|
||||
- test-llvm17-go122
|
||||
- test-llvm15-go119
|
||||
# This tests LLVM 18 support when linking against system libraries.
|
||||
- test-llvm18-go122
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-17-${{ matrix.os }}-v1
|
||||
key: llvm-source-18-${{ matrix.os }}-v2
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-17-${{ matrix.os }}-v1
|
||||
key: llvm-build-18-${{ matrix.os }}-v2
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
version: [16, 17]
|
||||
version: [16, 17, 18]
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
@@ -152,8 +152,8 @@ jobs:
|
||||
- name: Check binary
|
||||
run: tinygo version
|
||||
- name: Build TinyGo (default LLVM)
|
||||
if: matrix.version == 17
|
||||
if: matrix.version == 18
|
||||
run: go install
|
||||
- name: Check binary
|
||||
if: matrix.version == 17
|
||||
if: matrix.version == 18
|
||||
run: tinygo version
|
||||
|
||||
+24
-20
@@ -24,7 +24,7 @@ jobs:
|
||||
# tar: needed for actions/cache@v4
|
||||
# git+openssh: needed for checkout (I think?)
|
||||
# ruby: needed to install fpm
|
||||
run: apk add tar git openssh make g++ ruby
|
||||
run: apk add tar git openssh make g++ ruby-dev
|
||||
- name: Work around CVE-2022-24765
|
||||
# We're not on a multi-user machine, so this is safe.
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-17-linux-alpine-v1
|
||||
key: llvm-source-18-linux-alpine-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-17-linux-alpine-v1
|
||||
key: llvm-build-18-linux-alpine-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -113,6 +113,8 @@ jobs:
|
||||
gem install --version 4.0.7 public_suffix
|
||||
gem install --version 2.7.6 dotenv
|
||||
gem install --no-document fpm
|
||||
- name: Run linter
|
||||
run: make lint
|
||||
- name: Build TinyGo release
|
||||
run: |
|
||||
make release deb -j3 STATIC=1
|
||||
@@ -132,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:
|
||||
@@ -152,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
|
||||
@@ -185,16 +189,16 @@ 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
|
||||
with:
|
||||
key: llvm-source-17-linux-asserts-v1
|
||||
key: llvm-source-18-linux-asserts-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
@@ -219,7 +223,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-17-linux-asserts-v1
|
||||
key: llvm-build-18-linux-asserts-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -307,7 +311,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-17-linux-v1
|
||||
key: llvm-source-18-linux-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
@@ -332,7 +336,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-17-linux-${{ matrix.goarch }}-v1
|
||||
key: llvm-build-18-linux-${{ matrix.goarch }}-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -356,13 +360,13 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-${{ matrix.goarch }}-v3
|
||||
key: binaryen-linux-${{ matrix.goarch }}-v4
|
||||
path: build/wasm-opt
|
||||
- name: Build Binaryen
|
||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
sudo apt-get install --no-install-recommends ninja-build
|
||||
git submodule update --init --recursive lib/binaryen
|
||||
git submodule update --init lib/binaryen
|
||||
make CROSS=${{ matrix.toolchain }} binaryen
|
||||
- name: Install fpm
|
||||
run: |
|
||||
|
||||
@@ -35,8 +35,8 @@ jobs:
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
tinygo/llvm-17
|
||||
ghcr.io/${{ github.repository_owner }}/llvm-17
|
||||
tinygo/llvm-18
|
||||
ghcr.io/${{ github.repository_owner }}/llvm-18
|
||||
tags: |
|
||||
type=sha,format=long
|
||||
type=raw,value=latest
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-17-linux-nix-v1
|
||||
key: llvm-source-18-linux-nix-v1
|
||||
path: |
|
||||
llvm-project/compiler-rt
|
||||
- name: Download LLVM source
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
# still works after checking out the dev branch (that is, when going from LLVM
|
||||
# 16 to LLVM 17 for example, both Clang 16 and Clang 17 are installed).
|
||||
|
||||
echo 'deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main' | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
echo 'deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main' | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get install --no-install-recommends -y \
|
||||
llvm-17-dev \
|
||||
clang-17 \
|
||||
libclang-17-dev \
|
||||
lld-17
|
||||
llvm-18-dev \
|
||||
clang-18 \
|
||||
libclang-18-dev \
|
||||
lld-18
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-17-sizediff-v1
|
||||
key: llvm-source-18-sizediff-v1
|
||||
path: |
|
||||
llvm-project/compiler-rt
|
||||
- name: Download LLVM source
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: go-cache-linux-sizediff-v1-${{ hashFiles('go.mod') }}
|
||||
key: go-cache-linux-sizediff-v2-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-17-windows-v1
|
||||
key: llvm-source-18-windows-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-17-windows-v1
|
||||
key: llvm-build-18-windows-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -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
@@ -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/*
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
@@ -85,7 +85,7 @@ Now that we have a working static build, it's time to make a release tarball:
|
||||
|
||||
If you did not clone the repository with the `--recursive` option, you will get errors until you initialize the project submodules:
|
||||
|
||||
git submodule update --init --recursive
|
||||
git submodule update --init
|
||||
|
||||
The release tarball is stored in build/release.tar.gz, and can be extracted with
|
||||
the following command (for example in ~/lib):
|
||||
|
||||
@@ -1,3 +1,74 @@
|
||||
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
|
||||
---
|
||||
|
||||
* **general**
|
||||
* update the `net` submodule to updated version with `Buffers` implementation
|
||||
|
||||
* **compiler**
|
||||
* `syscall`: add wasm_unknown tag to some additional files so it can compile more code
|
||||
|
||||
* **standard library**
|
||||
* `runtime`: add Frame.Entry field
|
||||
|
||||
|
||||
0.31.1
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ COPY . /tinygo
|
||||
|
||||
# build the compiler and tools
|
||||
RUN cd /tinygo/ && \
|
||||
git submodule update --init --recursive && \
|
||||
git submodule update --init && \
|
||||
make gen-device -j4 && \
|
||||
make build/release
|
||||
|
||||
|
||||
+92
-31
@@ -10,7 +10,7 @@ LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
|
||||
|
||||
# Try to autodetect LLVM build tools.
|
||||
# Versions are listed here in descending priority order.
|
||||
LLVM_VERSIONS = 17 16 15
|
||||
LLVM_VERSIONS = 18 17 16 15
|
||||
errifempty = $(if $(1),$(1),$(error $(2)))
|
||||
detect = $(shell which $(call errifempty,$(firstword $(foreach p,$(2),$(shell command -v $(p) 2> /dev/null && echo $(p)))),failed to locate $(1) at any of: $(2)))
|
||||
toolSearchPathsVersion = $(1)-$(2)
|
||||
@@ -31,6 +31,7 @@ export GOROOT = $(shell $(GO) env GOROOT)
|
||||
|
||||
# Flags to pass to go test.
|
||||
GOTESTFLAGS ?=
|
||||
GOTESTPKGS ?= ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
||||
|
||||
# tinygo binary for tests
|
||||
TINYGO ?= $(call detect,tinygo,tinygo $(CURDIR)/build/tinygo)
|
||||
@@ -110,7 +111,7 @@ endif
|
||||
|
||||
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp
|
||||
|
||||
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendhlsl frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsdriver windowsmanifest
|
||||
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontenddriver frontendhlsl frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsdriver windowsmanifest
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
EXE = .exe
|
||||
@@ -146,7 +147,7 @@ endif
|
||||
MD5SUM ?= md5sum
|
||||
|
||||
# Libraries that should be linked in for the statically linked Clang.
|
||||
CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
|
||||
CLANG_LIB_NAMES = clangAnalysis clangAPINotes clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
|
||||
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
|
||||
|
||||
# Libraries that should be linked in for the statically linked LLD.
|
||||
@@ -165,7 +166,7 @@ LIB_NAMES = clang $(CLANG_LIB_NAMES) $(LLD_LIB_NAMES) $(EXTRA_LIB_NAMES)
|
||||
# library path (for ninja).
|
||||
# This list also includes a few tools that are necessary as part of the full
|
||||
# TinyGo build.
|
||||
NINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm $(addprefix lib/lib,$(addsuffix .a,$(LIB_NAMES)))
|
||||
NINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm lld $(addprefix lib/lib,$(addsuffix .a,$(LIB_NAMES)))
|
||||
|
||||
# For static linking.
|
||||
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
|
||||
@@ -190,7 +191,7 @@ gen-device: gen-device-stm32
|
||||
endif
|
||||
|
||||
gen-device-avr:
|
||||
@if [ ! -e lib/avr/README.md ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init --recursive"; exit 1; fi
|
||||
@if [ ! -e lib/avr/README.md ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
||||
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
|
||||
./build/gen-device-avr lib/avr/packs/atmega src/device/avr/
|
||||
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
|
||||
@@ -238,7 +239,7 @@ gen-device-renesas: build/gen-device-svd
|
||||
|
||||
# Get LLVM sources.
|
||||
$(LLVM_PROJECTDIR)/llvm:
|
||||
git clone -b xtensa_release_17.0.1 --depth=1 https://github.com/espressif/llvm-project $(LLVM_PROJECTDIR)
|
||||
git clone -b tinygo_xtensa_release_18.1.2 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
|
||||
llvm-source: $(LLVM_PROJECTDIR)/llvm
|
||||
|
||||
# Configure LLVM.
|
||||
@@ -264,9 +265,14 @@ endif
|
||||
.PHONY: wasi-libc
|
||||
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
||||
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 --recursive"; exit 1; fi
|
||||
@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
|
||||
@@ -283,7 +289,7 @@ tinygo:
|
||||
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags "byollvm osusergo" -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
|
||||
test: wasi-libc check-nodejs-version
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags "byollvm osusergo" ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags "byollvm osusergo" $(GOTESTPKGS)
|
||||
|
||||
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
||||
TEST_PACKAGES_SLOW = \
|
||||
@@ -426,17 +432,38 @@ tinygo-bench-fast:
|
||||
|
||||
# Same thing, except for wasi rather than the current platform.
|
||||
tinygo-test-wasi:
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_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 wasi $(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 wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-bench-wasi-fast:
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST)
|
||||
$(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-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:
|
||||
@@ -444,7 +471,7 @@ test-corpus:
|
||||
test-corpus-fast:
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus -short . -corpus=testdata/corpus.yaml
|
||||
test-corpus-wasi: wasi-libc
|
||||
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 -target=wasi
|
||||
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 -target=wasip1
|
||||
|
||||
tinygo-baremetal:
|
||||
# Regression tests that run on a baremetal target and don't fit in either main_test.go or smoketest.
|
||||
@@ -490,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
|
||||
@@ -522,7 +549,9 @@ 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
|
||||
endif
|
||||
# test all targets/boards
|
||||
@@ -598,6 +627,8 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pca10056-s140v7 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pca10059-s140v7 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=reelboard-s140v7 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=wioterminal examples/blinky1
|
||||
@@ -616,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
|
||||
@@ -654,6 +685,8 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=badger2040-w examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=tufty2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=thingplus-rp2040 examples/blinky1
|
||||
@@ -686,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
|
||||
@@ -703,6 +736,8 @@ ifneq ($(STM32), 0)
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=nucleo-l432kc examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=nucleo-l476rg examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=nucleo-l552ze examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=nucleo-wl55jc examples/blinky1
|
||||
@@ -726,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
|
||||
@@ -753,20 +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 mch2022 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/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
|
||||
@@ -818,7 +855,10 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
|
||||
@mkdir -p build/release/tinygo/lib/nrfx
|
||||
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libc
|
||||
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libm
|
||||
@mkdir -p build/release/tinygo/lib/wasi-libc
|
||||
@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
|
||||
@@ -869,7 +909,16 @@ endif
|
||||
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
||||
@cp -rp lib/picolibc/newlib/libm/math build/release/tinygo/lib/picolibc/newlib/libm
|
||||
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
||||
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
||||
@cp -rp lib/wasi-libc/libc-bottom-half/headers/public build/release/tinygo/lib/wasi-libc/libc-bottom-half/headers
|
||||
@cp -rp lib/wasi-libc/libc-top-half/musl/arch/generic build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
||||
@cp -rp lib/wasi-libc/libc-top-half/musl/arch/wasm32 build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/internal build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/math build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||
@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
|
||||
@@ -896,3 +945,15 @@ ifneq ($(RELEASEONLY), 1)
|
||||
release: build/release
|
||||
deb: build/release
|
||||
endif
|
||||
|
||||
lint:
|
||||
go run github.com/mgechev/revive -version
|
||||
# TODO: lint more directories!
|
||||
# revive.toml isn't flexible enough to filter out just one kind of error from a checker, so do it with grep here.
|
||||
# Can't use grep with friendly formatter. Plain output isn't too bad, though.
|
||||
# Use 'grep .' to get rid of stray blank line
|
||||
go run github.com/mgechev/revive -config revive.toml compiler/... src/{os,reflect}/*.go | grep -v "should have comment or be unexported" | grep '.' | awk '{print}; END {exit NR>0}'
|
||||
|
||||
spell:
|
||||
# Check for typos in comments. Skip git submodules etc.
|
||||
go run github.com/client9/misspell/cmd/misspell -i 'ackward,devided,extint,inbetween,programmmer,rela' $$( find . -depth 1 -type d | egrep -w -v 'lib|llvm|src/net' )
|
||||
|
||||
@@ -41,7 +41,7 @@ tinygo flash -target arduino examples/blinky1
|
||||
|
||||
TinyGo is very useful for compiling programs both for use in browsers (WASM) as well as for use on servers and other edge devices (WASI).
|
||||
|
||||
TinyGo programs can run in Fastly Compute@Edge (https://developer.fastly.com/learning/compute/go/), Fermyon Spin (https://developer.fermyon.com/spin/go-components), wazero (https://wazero.io/languages/tinygo/) and many other WebAssembly runtimes.
|
||||
TinyGo programs can run in [Fastly Compute](https://www.fastly.com/documentation/guides/compute/go/), [Fermyon Spin](https://developer.fermyon.com/spin/go-components), [wazero](https://wazero.io/languages/tinygo/) and many other WebAssembly runtimes.
|
||||
|
||||
Here is a small TinyGo program for use by a WASI host application:
|
||||
|
||||
@@ -54,14 +54,14 @@ func add(x, y uint32) uint32 {
|
||||
return x + y
|
||||
}
|
||||
|
||||
// main is required for the `wasi` target, even if it isn't used.
|
||||
// main is required for the `wasip1` target, even if it isn't used.
|
||||
func main() {}
|
||||
```
|
||||
|
||||
This compiles the above TinyGo program for use on any WASI runtime:
|
||||
|
||||
```shell
|
||||
tinygo build -o main.wasm -target=wasi main.go
|
||||
tinygo build -o main.wasm -target=wasip1 main.go
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
+16
-6
@@ -78,17 +78,27 @@ func makeArchive(arfile *os.File, objs []string) error {
|
||||
} else if dbg, err := wasm.Parse(objfile); err == nil {
|
||||
for _, s := range dbg.Sections {
|
||||
switch section := s.(type) {
|
||||
case *wasm.SectionImport:
|
||||
for _, ln := range section.Entries {
|
||||
|
||||
if ln.Kind != wasm.ExtKindFunction {
|
||||
// Not a function
|
||||
case *wasm.SectionLinking:
|
||||
for _, symbol := range section.Symbols {
|
||||
if symbol.Flags&wasm.LinkingSymbolFlagUndefined != 0 {
|
||||
// Don't list undefined functions.
|
||||
continue
|
||||
}
|
||||
if symbol.Flags&wasm.LinkingSymbolFlagBindingLocal != 0 {
|
||||
// Don't include local symbols.
|
||||
continue
|
||||
}
|
||||
if symbol.Kind != wasm.LinkingSymbolKindFunction && symbol.Kind != wasm.LinkingSymbolKindData {
|
||||
// Link functions and data symbols.
|
||||
// Some data symbols need to be included, such as
|
||||
// __log_data.
|
||||
continue
|
||||
}
|
||||
// Include in the archive.
|
||||
symbolTable = append(symbolTable, struct {
|
||||
name string
|
||||
fileIndex int
|
||||
}{ln.Field, i})
|
||||
}{symbol.Name, i})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+79
-3
@@ -168,6 +168,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
return BuildResult{}, errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
||||
}
|
||||
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
||||
case "wasmbuiltins":
|
||||
libcJob, unlock, err := WasmBuiltins.load(config, tmpdir)
|
||||
if err != nil {
|
||||
return BuildResult{}, err
|
||||
}
|
||||
defer unlock()
|
||||
libcDependencies = append(libcDependencies, libcJob)
|
||||
case "mingw-w64":
|
||||
_, unlock, err := MinGW.load(config, tmpdir)
|
||||
if err != nil {
|
||||
@@ -200,6 +207,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
MaxStackAlloc: config.MaxStackAlloc(),
|
||||
NeedsStackObjects: config.NeedsStackObjects(),
|
||||
Debug: !config.Options.SkipDWARF, // emit DWARF except when -internal-nodwarf is passed
|
||||
PanicStrategy: config.PanicStrategy(),
|
||||
}
|
||||
|
||||
// Load the target machine, which is the LLVM object that contains all
|
||||
@@ -765,7 +773,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
if sizeLevel >= 2 {
|
||||
// Workaround with roughly the same effect as
|
||||
// https://reviews.llvm.org/D119342.
|
||||
// Can hopefully be removed in LLVM 18.
|
||||
// Can hopefully be removed in LLVM 19.
|
||||
ldflags = append(ldflags,
|
||||
"-mllvm", "--rotation-max-header-size=0")
|
||||
}
|
||||
@@ -817,14 +825,26 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
||||
args = append(args, "--asyncify")
|
||||
}
|
||||
|
||||
exeunopt := result.Executable
|
||||
|
||||
if config.Options.Work {
|
||||
// Keep the work direction around => don't overwrite the .wasm binary with the optimized version
|
||||
exeunopt += ".pre-wasm-opt"
|
||||
os.Rename(result.Executable, exeunopt)
|
||||
}
|
||||
|
||||
args = append(args,
|
||||
opt,
|
||||
"-g",
|
||||
result.Executable,
|
||||
exeunopt,
|
||||
"--output", result.Executable,
|
||||
)
|
||||
|
||||
cmd := exec.Command(goenv.Get("WASMOPT"), args...)
|
||||
wasmopt := goenv.Get("WASMOPT")
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands(wasmopt, args...)
|
||||
}
|
||||
cmd := exec.Command(wasmopt, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
@@ -834,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))
|
||||
|
||||
@@ -33,7 +33,8 @@ func TestClangAttributes(t *testing.T) {
|
||||
"k210",
|
||||
"nintendoswitch",
|
||||
"riscv-qemu",
|
||||
"wasi",
|
||||
"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" {
|
||||
|
||||
+5
-7
@@ -8,14 +8,14 @@ import (
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
// These are the GENERIC_SOURCES according to CMakeList.txt.
|
||||
// These are the GENERIC_SOURCES according to CMakeList.txt except for
|
||||
// divmodsi4.c and udivmodsi4.c.
|
||||
var genericBuiltins = []string{
|
||||
"absvdi2.c",
|
||||
"absvsi2.c",
|
||||
"absvti2.c",
|
||||
"adddf3.c",
|
||||
"addsf3.c",
|
||||
"addtf3.c",
|
||||
"addvdi3.c",
|
||||
"addvsi3.c",
|
||||
"addvti3.c",
|
||||
@@ -40,12 +40,12 @@ var genericBuiltins = []string{
|
||||
"divdf3.c",
|
||||
"divdi3.c",
|
||||
"divmoddi4.c",
|
||||
//"divmodsi4.c",
|
||||
"divmodti4.c",
|
||||
"divsc3.c",
|
||||
"divsf3.c",
|
||||
"divsi3.c",
|
||||
"divtc3.c",
|
||||
"divti3.c",
|
||||
"divtf3.c",
|
||||
"extendsfdf2.c",
|
||||
"extendhfsf2.c",
|
||||
"ffsdi2.c",
|
||||
@@ -91,7 +91,6 @@ var genericBuiltins = []string{
|
||||
"mulsc3.c",
|
||||
"mulsf3.c",
|
||||
"multi3.c",
|
||||
"multf3.c",
|
||||
"mulvdi3.c",
|
||||
"mulvsi3.c",
|
||||
"mulvti3.c",
|
||||
@@ -111,13 +110,11 @@ var genericBuiltins = []string{
|
||||
"popcountti2.c",
|
||||
"powidf2.c",
|
||||
"powisf2.c",
|
||||
"powitf2.c",
|
||||
"subdf3.c",
|
||||
"subsf3.c",
|
||||
"subvdi3.c",
|
||||
"subvsi3.c",
|
||||
"subvti3.c",
|
||||
"subtf3.c",
|
||||
"trampoline_setup.c",
|
||||
"truncdfhf2.c",
|
||||
"truncdfsf2.c",
|
||||
@@ -126,6 +123,7 @@ var genericBuiltins = []string{
|
||||
"ucmpti2.c",
|
||||
"udivdi3.c",
|
||||
"udivmoddi4.c",
|
||||
//"udivmodsi4.c",
|
||||
"udivmodti4.c",
|
||||
"udivsi3.c",
|
||||
"udivti3.c",
|
||||
|
||||
+8
-7
@@ -82,10 +82,10 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
||||
// Parse the arguments.
|
||||
const OptTable &OptTbl = getDriverOptTable();
|
||||
|
||||
const unsigned IncludedFlagsBitmask = options::CC1AsOption;
|
||||
llvm::opt::Visibility VisibilityMask(options::CC1AsOption);
|
||||
unsigned MissingArgIndex, MissingArgCount;
|
||||
InputArgList Args = OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount,
|
||||
IncludedFlagsBitmask);
|
||||
InputArgList Args =
|
||||
OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, VisibilityMask);
|
||||
|
||||
// Check for missing argument error.
|
||||
if (MissingArgCount) {
|
||||
@@ -98,7 +98,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
||||
for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
|
||||
auto ArgString = A->getAsString(Args);
|
||||
std::string Nearest;
|
||||
if (OptTbl.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
|
||||
if (OptTbl.findNearest(ArgString, Nearest, VisibilityMask) > 1)
|
||||
Diags.Report(diag::err_drv_unknown_argument) << ArgString;
|
||||
else
|
||||
Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
|
||||
@@ -521,9 +521,10 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
|
||||
if (Asm.ShowHelp) {
|
||||
getDriverOptTable().printHelp(
|
||||
llvm::outs(), "clang -cc1as [options] file...",
|
||||
"Clang Integrated Assembler",
|
||||
/*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
|
||||
/*ShowAllAliases=*/false);
|
||||
"Clang Integrated Assembler", /*ShowHidden=*/false,
|
||||
/*ShowAllAliases=*/false,
|
||||
llvm::opt::Visibility(driver::options::CC1AsOption));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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{
|
||||
|
||||
@@ -41,9 +41,9 @@ func TestBinarySize(t *testing.T) {
|
||||
// This is a small number of very diverse targets that we want to test.
|
||||
tests := []sizeTest{
|
||||
// microcontrollers
|
||||
{"hifive1b", "examples/echo", 4476, 280, 0, 2252},
|
||||
{"microbit", "examples/serial", 2724, 388, 8, 2256},
|
||||
{"wioterminal", "examples/pininterrupt", 5996, 1484, 116, 6816},
|
||||
{"hifive1b", "examples/echo", 4484, 280, 0, 2252},
|
||||
{"microbit", "examples/serial", 2732, 388, 8, 2256},
|
||||
{"wioterminal", "examples/pininterrupt", 6016, 1484, 116, 6816},
|
||||
|
||||
// TODO: also check wasm. Right now this is difficult, because
|
||||
// wasm binaries are run through wasm-opt and therefore the
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
var WasmBuiltins = Library{
|
||||
name: "wasmbuiltins",
|
||||
makeHeaders: func(target, includeDir string) error {
|
||||
if err := os.Mkdir(includeDir+"/bits", 0o777); err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Create(includeDir + "/bits/alltypes.h")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.Write([]byte(wasmAllTypes)); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.Close()
|
||||
},
|
||||
cflags: func(target, headerPath string) []string {
|
||||
libcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc")
|
||||
return []string{
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
"-std=gnu11",
|
||||
"-nostdlibinc",
|
||||
"-isystem", libcDir + "/libc-top-half/musl/arch/wasm32",
|
||||
"-isystem", libcDir + "/libc-top-half/musl/arch/generic",
|
||||
"-isystem", libcDir + "/libc-top-half/musl/src/internal",
|
||||
"-isystem", libcDir + "/libc-top-half/musl/src/include",
|
||||
"-isystem", libcDir + "/libc-top-half/musl/include",
|
||||
"-isystem", libcDir + "/libc-bottom-half/headers/public",
|
||||
"-I" + headerPath,
|
||||
}
|
||||
},
|
||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") },
|
||||
librarySources: func(target string) ([]string, error) {
|
||||
return []string{
|
||||
// memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and
|
||||
// llvm.memset.* LLVM intrinsics.
|
||||
"libc-top-half/musl/src/string/memcpy.c",
|
||||
"libc-top-half/musl/src/string/memmove.c",
|
||||
"libc-top-half/musl/src/string/memset.c",
|
||||
|
||||
// exp, exp2, and log are needed for LLVM math builtin functions
|
||||
// like llvm.exp.*.
|
||||
"libc-top-half/musl/src/math/__math_divzero.c",
|
||||
"libc-top-half/musl/src/math/__math_invalid.c",
|
||||
"libc-top-half/musl/src/math/__math_oflow.c",
|
||||
"libc-top-half/musl/src/math/__math_uflow.c",
|
||||
"libc-top-half/musl/src/math/__math_xflow.c",
|
||||
"libc-top-half/musl/src/math/exp.c",
|
||||
"libc-top-half/musl/src/math/exp_data.c",
|
||||
"libc-top-half/musl/src/math/exp2.c",
|
||||
"libc-top-half/musl/src/math/log.c",
|
||||
"libc-top-half/musl/src/math/log_data.c",
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
// alltypes.h for wasm-libc, using the types as defined inside Clang.
|
||||
const wasmAllTypes = `
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
|
||||
// This type is used internally in wasi-libc.
|
||||
typedef double double_t;
|
||||
`
|
||||
+1
-1
@@ -216,7 +216,7 @@ func (i simpleImporter) Import(path string) (*types.Package, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// formatDiagnostics formats the error message to be an indented comment. It
|
||||
// formatDiagnostic formats the error message to be an indented comment. It
|
||||
// also fixes Windows path name issues (backward slashes).
|
||||
func formatDiagnostic(err error) string {
|
||||
msg := err.Error()
|
||||
|
||||
+12
-2
@@ -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:]
|
||||
|
||||
@@ -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`},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !byollvm && !llvm15 && !llvm16
|
||||
//go:build !byollvm && llvm17
|
||||
|
||||
package cgo
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
//go:build !byollvm && !llvm15 && !llvm16 && !llvm17
|
||||
|
||||
package cgo
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -I/usr/include/llvm-18 -I/usr/include/llvm-c-18 -I/usr/lib/llvm-18/include
|
||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@18/include
|
||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@18/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/llvm18/include
|
||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-18/lib -lclang
|
||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@18/lib -lclang
|
||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@18/lib -lclang
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm18/lib -lclang
|
||||
*/
|
||||
import "C"
|
||||
+10
-5
@@ -74,7 +74,8 @@ func (c *Config) GOARM() string {
|
||||
|
||||
// BuildTags returns the complete list of build tags used during this build.
|
||||
func (c *Config) BuildTags() []string {
|
||||
tags := append(c.Target.BuildTags, []string{
|
||||
tags := append([]string(nil), c.Target.BuildTags...) // copy slice (avoid a race)
|
||||
tags = append(tags, []string{
|
||||
"tinygo", // that's the compiler
|
||||
"purego", // to get various crypto packages to work
|
||||
"math_big_pure_go", // to get math/big to work
|
||||
@@ -310,7 +311,11 @@ func (c *Config) CFlags(libclang bool) []string {
|
||||
)
|
||||
case "wasi-libc":
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
cflags = append(cflags, "--sysroot="+root+"/lib/wasi-libc/sysroot")
|
||||
cflags = append(cflags,
|
||||
"-nostdlibinc",
|
||||
"-isystem", root+"/lib/wasi-libc/sysroot/include")
|
||||
case "wasmbuiltins":
|
||||
// nothing to add (library is purely for builtins)
|
||||
case "mingw-w64":
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
path, _ := c.LibcPath("mingw-w64")
|
||||
@@ -475,9 +480,6 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
||||
return nil, fmt.Errorf("unknown OpenOCD transport: %#v", c.Target.OpenOCDTransport)
|
||||
}
|
||||
args = []string{"-f", "interface/" + openocdInterface + ".cfg"}
|
||||
for _, cmd := range c.Target.OpenOCDCommands {
|
||||
args = append(args, "-c", cmd)
|
||||
}
|
||||
if c.Target.OpenOCDTransport != "" {
|
||||
transport := c.Target.OpenOCDTransport
|
||||
if transport == "swd" {
|
||||
@@ -489,6 +491,9 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
||||
args = append(args, "-c", "transport select "+transport)
|
||||
}
|
||||
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
|
||||
for _, cmd := range c.Target.OpenOCDCommands {
|
||||
args = append(args, "-c", cmd)
|
||||
}
|
||||
return args, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -26,7 +26,7 @@ type TargetSpec struct {
|
||||
Inherits []string `json:"inherits,omitempty"`
|
||||
Triple string `json:"llvm-target,omitempty"`
|
||||
CPU string `json:"cpu,omitempty"`
|
||||
ABI string `json:"target-abi,omitempty"` // rougly equivalent to -mabi= flag
|
||||
ABI string `json:"target-abi,omitempty"` // roughly equivalent to -mabi= flag
|
||||
Features string `json:"features,omitempty"`
|
||||
GOOS string `json:"goos,omitempty"`
|
||||
GOARCH string `json:"goarch,omitempty"`
|
||||
@@ -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.
|
||||
@@ -319,11 +321,11 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||
case "arm64":
|
||||
spec.CPU = "generic"
|
||||
if goos == "darwin" {
|
||||
spec.Features = "+neon"
|
||||
spec.Features = "+fp-armv8,+neon"
|
||||
} else if goos == "windows" {
|
||||
spec.Features = "+neon,-fmv"
|
||||
spec.Features = "+fp-armv8,+neon,-fmv"
|
||||
} else { // linux
|
||||
spec.Features = "+neon,-fmv,-outline-atomics"
|
||||
spec.Features = "+fp-armv8,+neon,-fmv,-outline-atomics"
|
||||
}
|
||||
case "wasm":
|
||||
spec.CPU = "generic"
|
||||
|
||||
+6
-2
@@ -16,14 +16,18 @@ import "tinygo.org/x/go-llvm"
|
||||
|
||||
var stdlibAliases = map[string]string{
|
||||
// crypto packages
|
||||
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
|
||||
"crypto/ed25519/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
|
||||
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
|
||||
"crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
|
||||
"crypto/md5.block": "crypto/md5.blockGeneric",
|
||||
"crypto/sha1.block": "crypto/sha1.blockGeneric",
|
||||
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
|
||||
"crypto/sha256.block": "crypto/sha256.blockGeneric",
|
||||
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
|
||||
|
||||
// AES
|
||||
"crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock",
|
||||
"crypto/aes.encryptBlockAsm": "crypto/aes.encryptBlock",
|
||||
|
||||
// math package
|
||||
"math.archHypot": "math.hypot",
|
||||
"math.archMax": "math.max",
|
||||
|
||||
+2
-2
@@ -135,7 +135,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
|
||||
|
||||
// Calculate (^uintptr(0)) >> 1, which is the max value that fits in an
|
||||
// uintptr if uintptrs were signed.
|
||||
maxBufSize := llvm.ConstLShr(llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)), llvm.ConstInt(b.uintptrType, 1, false))
|
||||
maxBufSize := b.CreateLShr(llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)), llvm.ConstInt(b.uintptrType, 1, false), "")
|
||||
if elementSize > maxBufSize.ZExtValue() {
|
||||
b.addError(pos, fmt.Sprintf("channel element type is too big (%v bytes)", elementSize))
|
||||
return
|
||||
@@ -150,7 +150,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
|
||||
|
||||
// Make sure maxBufSize has the same type as bufSize.
|
||||
if maxBufSize.Type() != bufSize.Type() {
|
||||
maxBufSize = llvm.ConstZExt(maxBufSize, bufSize.Type())
|
||||
maxBufSize = b.CreateZExt(maxBufSize, bufSize.Type(), "")
|
||||
}
|
||||
|
||||
// Do the check for a too large (or negative) buffer size.
|
||||
|
||||
@@ -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, "")
|
||||
|
||||
+16
-4
@@ -56,6 +56,7 @@ type Config struct {
|
||||
MaxStackAlloc uint64
|
||||
NeedsStackObjects bool
|
||||
Debug bool // Whether to emit debug information in the LLVM module.
|
||||
PanicStrategy string
|
||||
}
|
||||
|
||||
// compilerContext contains function-independent data that should still be
|
||||
@@ -1845,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)
|
||||
@@ -1855,6 +1856,13 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
supportsRecover = 1
|
||||
}
|
||||
return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil
|
||||
case name == "runtime.panicStrategy":
|
||||
// These constants are defined in src/runtime/panic.go.
|
||||
panicStrategy := map[string]uint64{
|
||||
"print": 1, // panicStrategyPrint
|
||||
"trap": 2, // panicStrategyTrap
|
||||
}[b.Config.PanicStrategy]
|
||||
return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
|
||||
case name == "runtime/interrupt.New":
|
||||
return b.createInterruptGlobal(instr)
|
||||
}
|
||||
@@ -2009,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)
|
||||
@@ -2173,7 +2183,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
|
||||
return llvm.Value{}, b.makeError(expr.Pos(), "todo: indexaddr: "+ptrTyp.String())
|
||||
}
|
||||
|
||||
// Make sure index is at least the size of uintptr becuase getelementptr
|
||||
// Make sure index is at least the size of uintptr because getelementptr
|
||||
// assumes index is a signed integer.
|
||||
index = b.extendInteger(index, expr.Index.Type(), b.uintptrType)
|
||||
|
||||
@@ -2215,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)
|
||||
@@ -2238,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.
|
||||
@@ -2549,7 +2561,7 @@ func (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Va
|
||||
sizeY := b.targetData.TypeAllocSize(y.Type())
|
||||
|
||||
// Check if the shift is bigger than the bit-width of the shifted value.
|
||||
// This is UB in LLVM, so it needs to be handled seperately.
|
||||
// This is UB in LLVM, so it needs to be handled separately.
|
||||
// The Go spec indirectly defines the result as 0.
|
||||
// Negative shifts are handled earlier, so we can treat y as unsigned.
|
||||
overshifted := b.CreateICmp(llvm.IntUGE, y, llvm.ConstInt(y.Type(), 8*sizeX, false), "shift.overflow")
|
||||
|
||||
+10
-8
@@ -124,16 +124,19 @@ func (c *compilerContext) pkgPathPtr(pkgpath string) llvm.Value {
|
||||
func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||
ms := c.program.MethodSets.MethodSet(typ)
|
||||
hasMethodSet := ms.Len() != 0
|
||||
if _, ok := typ.Underlying().(*types.Interface); ok {
|
||||
_, isInterface := typ.Underlying().(*types.Interface)
|
||||
if isInterface {
|
||||
hasMethodSet = false
|
||||
}
|
||||
|
||||
// As defined in https://pkg.go.dev/reflect#Type:
|
||||
// NumMethod returns the number of methods accessible using Method.
|
||||
// For a non-interface type, it returns the number of exported methods.
|
||||
// For an interface type, it returns the number of exported and unexported methods.
|
||||
var numMethods int
|
||||
if hasMethodSet {
|
||||
for i := 0; i < ms.Len(); i++ {
|
||||
if ms.At(i).Obj().Exported() {
|
||||
numMethods++
|
||||
}
|
||||
for i := 0; i < ms.Len(); i++ {
|
||||
if isInterface || ms.At(i).Obj().Exported() {
|
||||
numMethods++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,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
|
||||
|
||||
@@ -23,6 +23,8 @@ func (b *builder) defineIntrinsicFunction() {
|
||||
b.createMemoryCopyImpl()
|
||||
case name == "runtime.memzero":
|
||||
b.createMemoryZeroImpl()
|
||||
case name == "runtime.stacksave":
|
||||
b.createStackSaveImpl()
|
||||
case name == "runtime.KeepAlive":
|
||||
b.createKeepAliveImpl()
|
||||
case strings.HasPrefix(name, "runtime/volatile.Load"):
|
||||
@@ -77,6 +79,14 @@ func (b *builder) createMemoryZeroImpl() {
|
||||
b.CreateRetVoid()
|
||||
}
|
||||
|
||||
// createStackSaveImpl creates a call to llvm.stacksave.p0 to read the current
|
||||
// stack pointer.
|
||||
func (b *builder) createStackSaveImpl() {
|
||||
b.createFunctionStart(true)
|
||||
sp := b.readStackPointer()
|
||||
b.CreateRet(sp)
|
||||
}
|
||||
|
||||
// Return the llvm.memset.p0.i8 function declaration.
|
||||
func (c *compilerContext) getMemsetFunc() llvm.Value {
|
||||
fnName := "llvm.memset.p0.i" + strconv.Itoa(c.uintptrType.IntTypeWidth())
|
||||
|
||||
+8
-2
@@ -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)
|
||||
}
|
||||
@@ -451,10 +453,14 @@ func (c *compilerContext) isThumb() bool {
|
||||
// readStackPointer emits a LLVM intrinsic call that returns the current stack
|
||||
// pointer as an *i8.
|
||||
func (b *builder) readStackPointer() llvm.Value {
|
||||
stacksave := b.mod.NamedFunction("llvm.stacksave")
|
||||
name := "llvm.stacksave.p0"
|
||||
if llvmutil.Version() < 18 {
|
||||
name = "llvm.stacksave" // backwards compatibility with LLVM 17 and below
|
||||
}
|
||||
stacksave := b.mod.NamedFunction(name)
|
||||
if stacksave.IsNil() {
|
||||
fnType := llvm.FunctionType(b.dataPtrType, nil, false)
|
||||
stacksave = llvm.AddFunction(b.mod, "llvm.stacksave", fnType)
|
||||
stacksave = llvm.AddFunction(b.mod, name, fnType)
|
||||
}
|
||||
return b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, "")
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Package llvmutil contains utility functions used across multiple compiler
|
||||
// packages. For example, they may be used by both the compiler pacakge and
|
||||
// packages. For example, they may be used by both the compiler package and
|
||||
// transformation packages.
|
||||
//
|
||||
// Normally, utility packages are avoided. However, in this case, the utility
|
||||
@@ -8,6 +8,9 @@
|
||||
package llvmutil
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
@@ -28,7 +31,7 @@ func CreateEntryBlockAlloca(builder llvm.Builder, t llvm.Type, name string) llvm
|
||||
}
|
||||
|
||||
// CreateTemporaryAlloca creates a new alloca in the entry block and adds
|
||||
// lifetime start infromation in the IR signalling that the alloca won't be used
|
||||
// lifetime start information in the IR signalling that the alloca won't be used
|
||||
// before this point.
|
||||
//
|
||||
// This is useful for creating temporary allocas for intrinsics. Don't forget to
|
||||
@@ -173,7 +176,7 @@ func SplitBasicBlock(builder llvm.Builder, afterInst llvm.Value, insertAfter llv
|
||||
return newBlock
|
||||
}
|
||||
|
||||
// Append the given values to a global array like llvm.used. The global might
|
||||
// AppendToGlobal appends the given values to a global array like llvm.used. The global might
|
||||
// not exist yet. The values can be any pointer type, they will be cast to i8*.
|
||||
func AppendToGlobal(mod llvm.Module, globalName string, values ...llvm.Value) {
|
||||
// Read the existing values in the llvm.used array (if it exists).
|
||||
@@ -203,3 +206,13 @@ func AppendToGlobal(mod llvm.Module, globalName string, values ...llvm.Value) {
|
||||
used.SetInitializer(usedInitializer)
|
||||
used.SetLinkage(llvm.AppendingLinkage)
|
||||
}
|
||||
|
||||
// Return the LLVM major version.
|
||||
func Version() int {
|
||||
majorStr := strings.Split(llvm.Version, ".")[0]
|
||||
major, err := strconv.Atoi(majorStr)
|
||||
if err != nil {
|
||||
panic("unexpected error while parsing LLVM version: " + err.Error()) // should not happen
|
||||
}
|
||||
return major
|
||||
}
|
||||
|
||||
+39
-9
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -81,11 +81,11 @@ entry:
|
||||
%select.send.value = alloca i32, align 4
|
||||
store i32 1, ptr %select.send.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %select.states.alloca)
|
||||
store ptr %ch1, ptr %select.states.alloca, align 8
|
||||
store ptr %ch1, ptr %select.states.alloca, align 4
|
||||
%select.states.alloca.repack1 = getelementptr inbounds %runtime.chanSelectState, ptr %select.states.alloca, i32 0, i32 1
|
||||
store ptr %select.send.value, ptr %select.states.alloca.repack1, align 4
|
||||
%0 = getelementptr inbounds [2 x %runtime.chanSelectState], ptr %select.states.alloca, i32 0, i32 1
|
||||
store ptr %ch2, ptr %0, align 8
|
||||
store ptr %ch2, ptr %0, align 4
|
||||
%.repack3 = getelementptr inbounds [2 x %runtime.chanSelectState], ptr %select.states.alloca, i32 0, i32 1, i32 1
|
||||
store ptr null, ptr %.repack3, align 4
|
||||
%select.result = call { i32, i1 } @runtime.tryChanSelect(ptr undef, ptr nonnull %select.states.alloca, i32 2, i32 2, ptr undef) #4
|
||||
|
||||
+3
-3
@@ -25,7 +25,7 @@ entry:
|
||||
%deferPtr = alloca ptr, align 4
|
||||
store ptr null, ptr %deferPtr, align 4
|
||||
%deferframe.buf = alloca %runtime.deferFrame, align 4
|
||||
%0 = call ptr @llvm.stacksave()
|
||||
%0 = call ptr @llvm.stacksave.p0()
|
||||
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
|
||||
store i32 0, ptr %defer.alloca, align 4
|
||||
%defer.alloca.repack15 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
||||
@@ -113,7 +113,7 @@ rundefers.end3: ; preds = %rundefers.loophead6
|
||||
}
|
||||
|
||||
; Function Attrs: nocallback nofree nosync nounwind willreturn
|
||||
declare ptr @llvm.stacksave() #3
|
||||
declare ptr @llvm.stacksave.p0() #3
|
||||
|
||||
declare void @runtime.setupDeferFrame(ptr dereferenceable_or_null(24), ptr, ptr) #2
|
||||
|
||||
@@ -136,7 +136,7 @@ entry:
|
||||
%deferPtr = alloca ptr, align 4
|
||||
store ptr null, ptr %deferPtr, align 4
|
||||
%deferframe.buf = alloca %runtime.deferFrame, align 4
|
||||
%0 = call ptr @llvm.stacksave()
|
||||
%0 = call ptr @llvm.stacksave.p0()
|
||||
call void @runtime.setupDeferFrame(ptr nonnull %deferframe.buf, ptr %0, ptr undef) #4
|
||||
store i32 0, ptr %defer.alloca, align 4
|
||||
%defer.alloca.repack22 = getelementptr inbounds { i32, ptr }, ptr %defer.alloca, i32 0, i32 1
|
||||
|
||||
Vendored
+48
-14
@@ -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
|
||||
|
||||
Vendored
+25
-25
@@ -16,9 +16,9 @@ target triple = "wasm32-unknown-wasi"
|
||||
@main.struct2 = hidden global ptr null, align 4
|
||||
@main.struct3 = hidden global ptr null, align 4
|
||||
@main.struct4 = hidden global ptr null, align 4
|
||||
@main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
|
||||
@main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
|
||||
@main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 8
|
||||
@main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
||||
@main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
||||
@main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
||||
@"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " }
|
||||
@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" }
|
||||
@"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 80, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4
|
||||
@@ -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,21 +102,21 @@ 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 8
|
||||
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 8
|
||||
%makeslice1 = call dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3
|
||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4
|
||||
%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 8
|
||||
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 8
|
||||
%makeslice3 = call dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3
|
||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4
|
||||
%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 8
|
||||
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
|
||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 8
|
||||
store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 2), align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ target triple = "wasm32-unknown-wasi"
|
||||
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 -62, ptr @"reflect/types.type:pointer:basic:int" }, align 4
|
||||
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:int" }, align 4
|
||||
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:named:error" }, align 4
|
||||
@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [7 x i8] } { i8 116, i16 0, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [7 x i8] c".error\00" }, align 4
|
||||
@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [7 x i8] } { i8 116, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [7 x i8] c".error\00" }, align 4
|
||||
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 84, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4
|
||||
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
|
||||
|
||||
Vendored
+8
-8
@@ -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
|
||||
@@ -122,8 +122,8 @@ entry:
|
||||
br i1 %slice.maxcap, label %slice.throw, label %slice.next
|
||||
|
||||
slice.next: ; preds = %entry
|
||||
%makeslice.cap = shl i32 %len, 1
|
||||
%makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||
%makeslice.cap = shl nuw i32 %len, 1
|
||||
%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
|
||||
@@ -164,8 +164,8 @@ entry:
|
||||
br i1 %slice.maxcap, label %slice.throw, label %slice.next
|
||||
|
||||
slice.next: ; preds = %entry
|
||||
%makeslice.cap = shl i32 %len, 2
|
||||
%makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||
%makeslice.cap = shl nuw i32 %len, 2
|
||||
%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
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -26,7 +26,7 @@ entry:
|
||||
%2 = insertvalue %main.hasPadding %1, i1 %s.b2, 2
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
|
||||
store %main.hasPadding %2, ptr %hashmap.key, align 8
|
||||
store %main.hasPadding %2, ptr %hashmap.key, align 4
|
||||
%3 = getelementptr inbounds i8, ptr %hashmap.key, i32 1
|
||||
call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5
|
||||
%4 = getelementptr inbounds i8, ptr %hashmap.key, i32 9
|
||||
@@ -59,7 +59,7 @@ entry:
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
store i32 5, ptr %hashmap.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 12, ptr nonnull %hashmap.key)
|
||||
store %main.hasPadding %2, ptr %hashmap.key, align 8
|
||||
store %main.hasPadding %2, ptr %hashmap.key, align 4
|
||||
%3 = getelementptr inbounds i8, ptr %hashmap.key, i32 1
|
||||
call void @runtime.memzero(ptr nonnull %3, i32 3, ptr undef) #5
|
||||
%4 = getelementptr inbounds i8, ptr %hashmap.key, i32 9
|
||||
@@ -80,7 +80,7 @@ entry:
|
||||
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %hashmap.value)
|
||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
|
||||
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 8
|
||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
||||
%hashmap.key.repack1 = getelementptr inbounds [2 x %main.hasPadding], ptr %hashmap.key, i32 0, i32 1
|
||||
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
||||
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
|
||||
@@ -108,7 +108,7 @@ entry:
|
||||
store i32 5, ptr %hashmap.value, align 4
|
||||
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %hashmap.key)
|
||||
%s.elt = extractvalue [2 x %main.hasPadding] %s, 0
|
||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 8
|
||||
store %main.hasPadding %s.elt, ptr %hashmap.key, align 4
|
||||
%hashmap.key.repack1 = getelementptr inbounds [2 x %main.hasPadding], ptr %hashmap.key, i32 0, i32 1
|
||||
%s.elt2 = extractvalue [2 x %main.hasPadding] %s, 1
|
||||
store %main.hasPadding %s.elt2, ptr %hashmap.key.repack1, align 4
|
||||
|
||||
+3
-2
@@ -51,6 +51,7 @@ func TestCorpus(t *testing.T) {
|
||||
if *testTarget != "" {
|
||||
target = *testTarget
|
||||
}
|
||||
isWASI := strings.HasPrefix(target, "wasi")
|
||||
|
||||
repos, err := loadRepos(*corpus)
|
||||
if err != nil {
|
||||
@@ -69,7 +70,7 @@ func TestCorpus(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if target == "wasi" && repo.SkipWASI {
|
||||
if isWASI && repo.SkipWASI {
|
||||
t.Skip("skip wasi")
|
||||
}
|
||||
if repo.Slow && testing.Short() {
|
||||
@@ -135,7 +136,7 @@ func TestCorpus(t *testing.T) {
|
||||
t.Run(dir.Pkg, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if target == "wasi" && dir.SkipWASI {
|
||||
if isWASI && dir.SkipWASI {
|
||||
t.Skip("skip wasi")
|
||||
}
|
||||
if dir.Slow && testing.Short() {
|
||||
|
||||
@@ -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
@@ -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")
|
||||
}
|
||||
@@ -18,10 +18,10 @@
|
||||
#
|
||||
# But you'll need a bit more to make TinyGo actually able to compile code:
|
||||
#
|
||||
# make llvm-source # fetch compiler-rt
|
||||
# git submodule update --init --recursive # fetch lots of other libraries and SVD files
|
||||
# make gen-device -j4 # build src/device/*/*.go files
|
||||
# make wasi-libc # build support for wasi/wasm
|
||||
# make llvm-source # fetch compiler-rt
|
||||
# git submodule update --init # fetch lots of other libraries and SVD files
|
||||
# make gen-device -j4 # build src/device/*/*.go files
|
||||
# make wasi-libc # build support for wasi/wasm
|
||||
#
|
||||
# With this, you should have an environment that can compile anything - except
|
||||
# for the Xtensa architecture (ESP8266/ESP32) because support for that lives in
|
||||
@@ -51,7 +51,6 @@
|
||||
go
|
||||
llvmPackages_17.llvm
|
||||
llvmPackages_17.libclang
|
||||
llvmPackages_17.libcxx
|
||||
# Additional dependencies needed at runtime, for building and/or
|
||||
# flashing.
|
||||
llvmPackages_17.lld
|
||||
@@ -78,7 +77,7 @@
|
||||
export MD5SUM=md5sum
|
||||
|
||||
# Ugly hack to make the Clang resources directory available.
|
||||
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_17.clang.cc.lib}/lib/clang/17"\"
|
||||
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_17.clang.cc.lib}/lib/clang/17\" -tags=llvm17"
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,35 +1,47 @@
|
||||
module github.com/tinygo-org/tinygo
|
||||
|
||||
go 1.18
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c
|
||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
||||
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee
|
||||
github.com/chromedp/chromedp v0.7.6
|
||||
github.com/client9/misspell v0.3.4
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||
github.com/mattn/go-colorable v0.1.8
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/mattn/go-tty v0.0.4
|
||||
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-20240106122909-c2c543540318
|
||||
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/chavacava/garif v0.1.0 // indirect
|
||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||
github.com/creack/goselect v0.1.2 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/fatih/structtag v1.2.0 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
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.16.0 // indirect
|
||||
)
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc h1:Yp49g+qqgQRPk/gcRSmAsXgnT16XPJ6Y5JM1poc6gYM=
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c h1:4T0Vj1UkGgcpkRrmn7SbokebnlfxJcMZPgWtOYACAAA=
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20240312204833-50275154210c/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
|
||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
|
||||
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
|
||||
github.com/chromedp/cdproto v0.0.0-20211126220118-81fa0469ad77/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
||||
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee h1:+SFdIVfQpG0s0DHYzou0kgfE0n0ZjKPwbiRJsXrZegU=
|
||||
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
||||
@@ -9,9 +13,17 @@ github.com/chromedp/chromedp v0.7.6 h1:2juGaktzjwULlsn+DnvIZXFUckEp5xs+GOBroaea+
|
||||
github.com/chromedp/chromedp v0.7.6/go.mod h1:ayT4YU/MGAALNfOg9gNrpGSAdnU51PMx+FCeuT1iXzo=
|
||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
@@ -31,43 +43,68 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
|
||||
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
|
||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0=
|
||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
|
||||
github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE=
|
||||
github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
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=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/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.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.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=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
tinygo.org/x/go-llvm v0.0.0-20240106122909-c2c543540318 h1:4KjZvPtcN1UwobevcGbdzeinx0L1i8HDdJu84bu7NI8=
|
||||
tinygo.org/x/go-llvm v0.0.0-20240106122909-c2c543540318/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
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-20240627184919-3b50c76783a8 h1:bLsZXRUBavt++CJlMN7sppNziqu3LyamESLhFJcpqFQ=
|
||||
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
|
||||
@@ -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
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
// Version of TinyGo.
|
||||
// Update this value before release of new version of software.
|
||||
const version = "0.31.1"
|
||||
const version = "0.33.0-dev"
|
||||
|
||||
var (
|
||||
// This variable is set at build time using -ldflags parameters.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Docker hub does a recursive clone, then checks the branch out,
|
||||
# so when a PR adds a submodule (or updates it), it fails.
|
||||
git submodule update --init --recursive
|
||||
git submodule update --init
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//go:build tools
|
||||
|
||||
// Install linter versions specified in go.mod
|
||||
// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idom
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/client9/misspell"
|
||||
_ "github.com/mgechev/revive"
|
||||
)
|
||||
+12
-1
@@ -427,9 +427,20 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||
if err != nil {
|
||||
return nil, mem, r.errorAt(inst, err)
|
||||
}
|
||||
// typecodePtr always point to the numMethod field in the type
|
||||
// description struct. The methodSet, when present, comes right
|
||||
// before the numMethod field (the compiler doesn't generate
|
||||
// method sets for concrete types without methods).
|
||||
// Considering that the compiler doesn't emit interface type
|
||||
// asserts for interfaces with no methods (as the always succeed)
|
||||
// then if the offset is zero, this assert must always fail.
|
||||
if typecodePtr.offset() == 0 {
|
||||
locals[inst.localIndex] = literalValue{uint8(0)}
|
||||
break
|
||||
}
|
||||
typecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))
|
||||
if err != nil {
|
||||
return nil, mem, r.errorAt(inst, err) // unlikely
|
||||
return nil, mem, r.errorAt(inst, err)
|
||||
}
|
||||
methodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)
|
||||
if err != nil {
|
||||
|
||||
Submodule
+1
Submodule lib/wasi-cli added at 6ae8261709
+5
-1
@@ -214,7 +214,7 @@ func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool)
|
||||
return merges, nil
|
||||
}
|
||||
|
||||
// needsSyscallPackage returns whether the syscall package should be overriden
|
||||
// needsSyscallPackage returns whether the syscall package should be overridden
|
||||
// with the TinyGo version. This is the case on some targets.
|
||||
func needsSyscallPackage(buildTags []string) bool {
|
||||
for _, tag := range buildTags {
|
||||
@@ -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 {
|
||||
|
||||
+58
-9
@@ -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.
|
||||
//
|
||||
@@ -430,7 +479,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
||||
var files []*ast.File
|
||||
var fileErrs []error
|
||||
|
||||
// Parse all files (incuding CgoFiles).
|
||||
// Parse all files (including CgoFiles).
|
||||
parseFile := func(file string) {
|
||||
if !filepath.IsAbs(file) {
|
||||
file = filepath.Join(p.Dir, file)
|
||||
|
||||
@@ -285,7 +285,7 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
// Tests are always run in the package directory.
|
||||
cmd.Dir = result.MainDir
|
||||
|
||||
// wasmtime is the default emulator used for `-target=wasi`. wasmtime
|
||||
// wasmtime is the default emulator used for `-target=wasip1`. wasmtime
|
||||
// is a WebAssembly runtime CLI with WASI enabled by default. However,
|
||||
// only stdio are allowed by default. For example, while STDOUT routes
|
||||
// to the host, other files don't. It also does not inherit environment
|
||||
@@ -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...)
|
||||
}
|
||||
@@ -1033,9 +1075,10 @@ func findFATMounts(options *compileopts.Options) ([]mountPoint, error) {
|
||||
if fstype != "vfat" {
|
||||
continue
|
||||
}
|
||||
fspath := strings.ReplaceAll(fields[1], "\\040", " ")
|
||||
points = append(points, mountPoint{
|
||||
name: filepath.Base(fields[1]),
|
||||
path: fields[1],
|
||||
name: filepath.Base(fspath),
|
||||
path: fspath,
|
||||
})
|
||||
}
|
||||
return points, nil
|
||||
@@ -1245,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 {
|
||||
@@ -1259,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)
|
||||
@@ -1296,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)
|
||||
@@ -1316,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)
|
||||
}
|
||||
}
|
||||
@@ -1411,7 +1470,7 @@ func main() {
|
||||
gc := flag.String("gc", "", "garbage collector to use (none, leaking, conservative)")
|
||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb, rtt)")
|
||||
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
||||
interpTimeout := flag.Duration("interp-timeout", 180*time.Second, "interp optimization pass timeout")
|
||||
var tags buildutil.TagsFlag
|
||||
@@ -1464,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")
|
||||
@@ -1543,6 +1608,8 @@ func main() {
|
||||
Monitor: *monitor,
|
||||
BaudRate: *baudrate,
|
||||
Timeout: *timeout,
|
||||
WITPackage: witPackage,
|
||||
WITWorld: witWorld,
|
||||
}
|
||||
if *printCommands {
|
||||
options.PrintCommands = printCommand
|
||||
@@ -1713,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 {
|
||||
|
||||
+86
-6
@@ -15,11 +15,13 @@ import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aykevl/go-wasm"
|
||||
"github.com/tinygo-org/tinygo/builder"
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
@@ -177,7 +179,11 @@ func TestBuild(t *testing.T) {
|
||||
})
|
||||
t.Run("WASI", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runPlatTests(optionsFromTarget("wasi", sema), tests, t)
|
||||
runPlatTests(optionsFromTarget("wasip1", sema), tests, t)
|
||||
})
|
||||
t.Run("WASIp2", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runPlatTests(optionsFromTarget("wasip2", sema), tests, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -190,7 +196,10 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
|
||||
isWebAssembly := options.Target == "wasi" || options.Target == "wasm" || (options.Target == "" && options.GOARCH == "wasm")
|
||||
// FIXME: this should really be:
|
||||
// isWebAssembly := strings.HasPrefix(spec.Triple, "wasm")
|
||||
isWASI := strings.HasPrefix(options.Target, "wasi")
|
||||
isWebAssembly := isWASI || strings.HasPrefix(options.Target, "wasm") || (options.Target == "" && strings.HasPrefix(options.GOARCH, "wasm"))
|
||||
|
||||
for _, name := range tests {
|
||||
if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") {
|
||||
@@ -230,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()
|
||||
@@ -250,13 +267,13 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
runTest("alias.go", options, t, nil, nil)
|
||||
})
|
||||
}
|
||||
if options.Target == "" || options.Target == "wasi" {
|
||||
if options.Target == "" || isWASI {
|
||||
t.Run("filesystem.go", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("filesystem.go", options, t, nil, nil)
|
||||
})
|
||||
}
|
||||
if options.Target == "" || options.Target == "wasi" || options.Target == "wasm" {
|
||||
if options.Target == "" || options.Target == "wasm" || isWASI {
|
||||
t.Run("rand.go", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("rand.go", options, t, nil, nil)
|
||||
@@ -292,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"),
|
||||
@@ -359,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
|
||||
}
|
||||
@@ -388,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
|
||||
}
|
||||
|
||||
@@ -404,6 +426,64 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
||||
}
|
||||
}
|
||||
|
||||
// Test WebAssembly files for certain properties.
|
||||
func TestWebAssembly(t *testing.T) {
|
||||
t.Parallel()
|
||||
type testCase struct {
|
||||
name string
|
||||
panicStrategy string
|
||||
imports []string
|
||||
}
|
||||
for _, tc := range []testCase{
|
||||
// Test whether there really are no imports when using -panic=trap. This
|
||||
// tests the bugfix for https://github.com/tinygo-org/tinygo/issues/4161.
|
||||
{name: "panic-default", imports: []string{"wasi_snapshot_preview1.fd_write"}},
|
||||
{name: "panic-trap", panicStrategy: "trap", imports: []string{}},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tmpdir := t.TempDir()
|
||||
options := optionsFromTarget("wasi", sema)
|
||||
options.PanicStrategy = tc.panicStrategy
|
||||
config, err := builder.NewConfig(&options)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
result, err := builder.Build("testdata/trivialpanic.go", ".wasm", tmpdir, config)
|
||||
if err != nil {
|
||||
t.Fatal("failed to build binary:", err)
|
||||
}
|
||||
f, err := os.Open(result.Binary)
|
||||
if err != nil {
|
||||
t.Fatal("could not open output binary:", err)
|
||||
}
|
||||
defer f.Close()
|
||||
module, err := wasm.Parse(f)
|
||||
if err != nil {
|
||||
t.Fatal("could not parse output binary:", err)
|
||||
}
|
||||
|
||||
// Test the list of imports.
|
||||
if tc.imports != nil {
|
||||
var imports []string
|
||||
for _, section := range module.Sections {
|
||||
switch section := section.(type) {
|
||||
case *wasm.SectionImport:
|
||||
for _, symbol := range section.Entries {
|
||||
imports = append(imports, symbol.Module+"."+symbol.Field)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !slices.Equal(imports, tc.imports) {
|
||||
t.Errorf("import list not as expected!\nexpected: %v\nactual: %v", tc.imports, imports)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -432,7 +512,7 @@ func TestTest(t *testing.T) {
|
||||
|
||||
// Node/Wasmtime
|
||||
targ{"WASM", optionsFromTarget("wasm", sema)},
|
||||
targ{"WASI", optionsFromTarget("wasi", sema)},
|
||||
targ{"WASI", optionsFromTarget("wasip1", sema)},
|
||||
)
|
||||
}
|
||||
for _, targ := range targs {
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
ignoreGeneratedHeader = false
|
||||
severity = "warning"
|
||||
confidence = 0.8
|
||||
errorCode = 0
|
||||
warningCode = 0
|
||||
|
||||
# Enable these as we fix them
|
||||
[rule.blank-imports]
|
||||
Exclude=["src/os/file_other.go"]
|
||||
[rule.context-as-argument]
|
||||
[rule.context-keys-type]
|
||||
[rule.dot-imports]
|
||||
Exclude=["**/*_test.go"]
|
||||
[rule.error-return]
|
||||
[rule.error-strings]
|
||||
[rule.error-naming]
|
||||
[rule.exported]
|
||||
Exclude=["src/reflect/*.go"]
|
||||
[rule.increment-decrement]
|
||||
[rule.var-naming]
|
||||
Exclude=["src/os/*.go"]
|
||||
[rule.var-declaration]
|
||||
#[rule.package-comments]
|
||||
[rule.range]
|
||||
[rule.receiver-naming]
|
||||
[rule.time-naming]
|
||||
[rule.unexported-return]
|
||||
#[rule.indent-error-flow]
|
||||
[rule.errorf]
|
||||
#[rule.empty-block]
|
||||
[rule.superfluous-else]
|
||||
#[rule.unused-parameter]
|
||||
[rule.unreachable-code]
|
||||
Exclude=["src/reflect/visiblefields_test.go", "src/reflect/all_test.go"]
|
||||
#[rule.redefines-builtin-id]
|
||||
@@ -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,4 +1,4 @@
|
||||
//go:build linux && !baremetal && !wasi
|
||||
//go:build linux && !baremetal && !wasip1 && !wasip2
|
||||
|
||||
// This implementation of crypto/rand uses the /dev/urandom pseudo-file to
|
||||
// generate random numbers.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func Count(b []byte, c byte) int {
|
||||
// Count the number of instances of a byte in a string.
|
||||
func CountString(s string, c byte) int {
|
||||
// Use a simple implementation, as there is no intrinsic that does this like we want.
|
||||
// Currently, the compiler does not generate zero-copy byte-string conversions, so this needs to be seperate from Count.
|
||||
// Currently, the compiler does not generate zero-copy byte-string conversions, so this needs to be separate from Count.
|
||||
n := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == c {
|
||||
@@ -216,7 +216,7 @@ func HashStrRev[T string | []byte](sep T) (uint32, uint32) {
|
||||
}
|
||||
|
||||
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
|
||||
// first occurence of substr in s, or -1 if not present.
|
||||
// first occurrence of substr in s, or -1 if not present.
|
||||
//
|
||||
// This function was removed in Go 1.22.
|
||||
func IndexRabinKarpBytes(s, sep []byte) int {
|
||||
|
||||
@@ -44,7 +44,7 @@ func Current() *Task {
|
||||
// This function may only be called when running on a goroutine stack, not when running on the system stack or in an interrupt.
|
||||
func Pause() {
|
||||
// Check whether the canary (the lowest address of the stack) is still
|
||||
// valid. If it is not, a stack overflow has occured.
|
||||
// valid. If it is not, a stack overflow has occurred.
|
||||
if *currentTask.state.canaryPtr != stackCanary {
|
||||
runtimePanic("goroutine stack overflow")
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ tinygo_startTask:
|
||||
// After return, exit this goroutine. This is a tail call.
|
||||
#if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25
|
||||
// Small memory devices (≤8kB flash) that do not have the long call
|
||||
// instruction availble will need to use rcall instead.
|
||||
// instruction available will need to use rcall instead.
|
||||
// Note that they will probably not be able to run more than the main
|
||||
// goroutine anyway, but this file is compiled for all AVRs so it needs to
|
||||
// compile at least.
|
||||
|
||||
@@ -78,7 +78,7 @@ tinygo_swapTask:
|
||||
// Switch to the new stack pointer (newStack).
|
||||
mov.n sp, a2
|
||||
|
||||
// Load a0, which is the previous return addres from before the previous
|
||||
// Load a0, which is the previous return address from before the previous
|
||||
// switch or the constructed return address to tinygo_startTask. This
|
||||
// register also stores the parent register window.
|
||||
l32i.n a0, sp, 0
|
||||
|
||||
@@ -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)
|
||||
@@ -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.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user