mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-05 11:37:46 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14b96f6f68 |
@@ -90,8 +90,6 @@ commands:
|
|||||||
name: Check Go code formatting
|
name: Check Go code formatting
|
||||||
command: make fmt-check lint
|
command: make fmt-check lint
|
||||||
- run: make gen-device -j4
|
- run: make gen-device -j4
|
||||||
# TODO: change this to -skip='TestErrors|TestWasm' with Go 1.20
|
|
||||||
- run: go test -tags=llvm<<parameters.llvm>> -short -run='TestBuild|TestTest|TestGetList|TestTraceback'
|
|
||||||
- run: make smoketest XTENSA=0
|
- run: make smoketest XTENSA=0
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: go-cache-v4-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
key: go-cache-v4-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
open_collective: tinygo
|
|
||||||
@@ -16,28 +16,24 @@ jobs:
|
|||||||
name: build-macos
|
name: build-macos
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# macos-13: amd64 (oldest supported version as of 18-10-2024)
|
# macos-12: amd64 (oldest supported version as of 05-02-2024)
|
||||||
# macos-14: arm64 (oldest arm64 version)
|
# macos-14: arm64 (oldest arm64 version)
|
||||||
os: [macos-13, macos-14]
|
os: [macos-12, macos-14]
|
||||||
include:
|
include:
|
||||||
- os: macos-13
|
- os: macos-12
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
- os: macos-14
|
- os: macos-14
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: exit early
|
|
||||||
run: command-does-not-exist
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen
|
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Extract TinyGo version
|
|
||||||
id: version
|
|
||||||
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
@@ -76,6 +72,7 @@ jobs:
|
|||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Build LLVM
|
- name: Build LLVM
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
# fetch LLVM source
|
# fetch LLVM source
|
||||||
rm -rf llvm-project
|
rm -rf llvm-project
|
||||||
@@ -103,13 +100,15 @@ jobs:
|
|||||||
- name: make gen-device
|
- name: make gen-device
|
||||||
run: make -j3 gen-device
|
run: make -j3 gen-device
|
||||||
- name: Test TinyGo
|
- name: Test TinyGo
|
||||||
|
shell: bash
|
||||||
run: make test GOTESTFLAGS="-short"
|
run: make test GOTESTFLAGS="-short"
|
||||||
- name: Build TinyGo release tarball
|
- name: Build TinyGo release tarball
|
||||||
run: make release -j3
|
run: make release -j3
|
||||||
- name: Test stdlib packages
|
- name: Test stdlib packages
|
||||||
run: make tinygo-test
|
run: make tinygo-test
|
||||||
- name: Make release artifact
|
- name: Make release artifact
|
||||||
run: cp -p build/release.tar.gz build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
|
shell: bash
|
||||||
|
run: cp -p build/release.tar.gz build/tinygo.darwin-${{ matrix.goarch }}.tar.gz
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
# Note: this release artifact is double-zipped, see:
|
# Note: this release artifact is double-zipped, see:
|
||||||
# https://github.com/actions/upload-artifact/issues/39
|
# https://github.com/actions/upload-artifact/issues/39
|
||||||
@@ -119,9 +118,10 @@ jobs:
|
|||||||
# We're doing the former here, to keep artifact uploads fast.
|
# We're doing the former here, to keep artifact uploads fast.
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: darwin-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
|
name: darwin-${{ matrix.goarch }}-double-zipped
|
||||||
path: build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
|
path: build/tinygo.darwin-${{ matrix.goarch }}.tar.gz
|
||||||
- name: Smoke tests
|
- name: Smoke tests
|
||||||
|
shell: bash
|
||||||
run: make smoketest TINYGO=$(PWD)/build/tinygo
|
run: make smoketest TINYGO=$(PWD)/build/tinygo
|
||||||
test-macos-homebrew:
|
test-macos-homebrew:
|
||||||
name: homebrew-install
|
name: homebrew-install
|
||||||
@@ -130,8 +130,6 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
version: [16, 17, 18]
|
version: [16, 17, 18]
|
||||||
steps:
|
steps:
|
||||||
- name: exit early
|
|
||||||
run: command-does-not-exist
|
|
||||||
- name: Set up Homebrew
|
- name: Set up Homebrew
|
||||||
uses: Homebrew/actions/setup-homebrew@master
|
uses: Homebrew/actions/setup-homebrew@master
|
||||||
- name: Fix Python symlinks
|
- name: Fix Python symlinks
|
||||||
|
|||||||
+14
-26
@@ -19,11 +19,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: golang:1.23-alpine
|
image: golang:1.23-alpine
|
||||||
outputs:
|
|
||||||
version: ${{ steps.version.outputs.version }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: exit early
|
|
||||||
run: command-does-not-exist
|
|
||||||
- name: Install apk dependencies
|
- name: Install apk dependencies
|
||||||
# tar: needed for actions/cache@v4
|
# tar: needed for actions/cache@v4
|
||||||
# git+openssh: needed for checkout (I think?)
|
# git+openssh: needed for checkout (I think?)
|
||||||
@@ -36,9 +32,6 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Extract TinyGo version
|
|
||||||
id: version
|
|
||||||
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -127,15 +120,15 @@ jobs:
|
|||||||
- name: Build TinyGo release
|
- name: Build TinyGo release
|
||||||
run: |
|
run: |
|
||||||
make release deb -j3 STATIC=1
|
make release deb -j3 STATIC=1
|
||||||
cp -p build/release.tar.gz /tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
|
cp -p build/release.tar.gz /tmp/tinygo.linux-amd64.tar.gz
|
||||||
cp -p build/release.deb /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
cp -p build/release.deb /tmp/tinygo_amd64.deb
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped-${{ steps.version.outputs.version }}
|
name: linux-amd64-double-zipped
|
||||||
path: |
|
path: |
|
||||||
/tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
|
/tmp/tinygo.linux-amd64.tar.gz
|
||||||
/tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
/tmp/tinygo_amd64.deb
|
||||||
test-linux-build:
|
test-linux-build:
|
||||||
# Test the binaries built in the build-linux job by running the smoke tests.
|
# Test the binaries built in the build-linux job by running the smoke tests.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -159,11 +152,11 @@ jobs:
|
|||||||
- name: Download release artifact
|
- name: Download release artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}
|
name: linux-amd64-double-zipped
|
||||||
- name: Extract release tarball
|
- name: Extract release tarball
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/lib
|
mkdir -p ~/lib
|
||||||
tar -C ~/lib -xf tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz
|
tar -C ~/lib -xf tinygo.linux-amd64.tar.gz
|
||||||
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
|
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
|
||||||
- run: make tinygo-test-wasip1-fast
|
- run: make tinygo-test-wasip1-fast
|
||||||
- run: make tinygo-test-wasip2-fast
|
- run: make tinygo-test-wasip2-fast
|
||||||
@@ -173,8 +166,6 @@ jobs:
|
|||||||
# potential bugs.
|
# potential bugs.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: exit early
|
|
||||||
run: command-does-not-exist
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -306,9 +297,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Get TinyGo version
|
|
||||||
id: version
|
|
||||||
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
|
||||||
- name: Install apt dependencies
|
- name: Install apt dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
@@ -393,11 +381,11 @@ jobs:
|
|||||||
- name: Download amd64 release
|
- name: Download amd64 release
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}
|
name: linux-amd64-double-zipped
|
||||||
- name: Extract amd64 release
|
- name: Extract amd64 release
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/release
|
mkdir -p build/release
|
||||||
tar -xf tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz -C build/release tinygo
|
tar -xf tinygo.linux-amd64.tar.gz -C build/release tinygo
|
||||||
- name: Modify release
|
- name: Modify release
|
||||||
run: |
|
run: |
|
||||||
cp -p build/tinygo build/release/tinygo/bin
|
cp -p build/tinygo build/release/tinygo/bin
|
||||||
@@ -405,12 +393,12 @@ jobs:
|
|||||||
- name: Create ${{ matrix.goarch }} release
|
- name: Create ${{ matrix.goarch }} release
|
||||||
run: |
|
run: |
|
||||||
make release deb RELEASEONLY=1 DEB_ARCH=${{ matrix.libc }}
|
make release deb RELEASEONLY=1 DEB_ARCH=${{ matrix.libc }}
|
||||||
cp -p build/release.tar.gz /tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz
|
cp -p build/release.tar.gz /tmp/tinygo.linux-${{ matrix.goarch }}.tar.gz
|
||||||
cp -p build/release.deb /tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb
|
cp -p build/release.deb /tmp/tinygo_${{ matrix.libc }}.deb
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
|
name: linux-${{ matrix.goarch }}-double-zipped
|
||||||
path: |
|
path: |
|
||||||
/tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz
|
/tmp/tinygo.linux-${{ matrix.goarch }}.tar.gz
|
||||||
/tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb
|
/tmp/tinygo_${{ matrix.libc }}.deb
|
||||||
|
|||||||
@@ -15,13 +15,6 @@ jobs:
|
|||||||
nix-test:
|
nix-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: exit early
|
|
||||||
run: command-does-not-exist
|
|
||||||
- name: Uninstall system LLVM
|
|
||||||
# Hack to work around issue where we still include system headers for
|
|
||||||
# some reason.
|
|
||||||
# See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668
|
|
||||||
run: sudo apt-get remove llvm-18
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Pull musl
|
- name: Pull musl
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: exit early
|
|
||||||
run: command-does-not-exist
|
|
||||||
# Prepare, install tools
|
# Prepare, install tools
|
||||||
- name: Add GOBIN to $PATH
|
- name: Add GOBIN to $PATH
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Extract the version string from the source code, to be stored in a variable.
|
|
||||||
grep 'const version' goenv/version.go | sed 's/^const version = "\(.*\)"$/version=\1/g'
|
|
||||||
@@ -14,8 +14,6 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
outputs:
|
|
||||||
version: ${{ steps.version.outputs.version }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Configure pagefile
|
- name: Configure pagefile
|
||||||
uses: al-cheb/configure-pagefile-action@v1.4
|
uses: al-cheb/configure-pagefile-action@v1.4
|
||||||
@@ -23,30 +21,22 @@ jobs:
|
|||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
#- uses: brechtm/setup-scoop@v2
|
- uses: brechtm/setup-scoop@v2
|
||||||
# with:
|
with:
|
||||||
# scoop_update: 'false'
|
scoop_update: 'false'
|
||||||
#- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
# shell: bash
|
shell: bash
|
||||||
# run: |
|
run: |
|
||||||
# scoop install ninja binaryen
|
scoop install ninja binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: submodules
|
with:
|
||||||
shell: bash
|
submodules: true
|
||||||
run: git submodule update --init lib/mingw-w64
|
- name: Install Go
|
||||||
- name: Extract TinyGo version
|
uses: actions/setup-go@v5
|
||||||
id: version
|
with:
|
||||||
shell: bash
|
go-version: '1.23'
|
||||||
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
cache: true
|
||||||
- name: command
|
|
||||||
shell: bash
|
|
||||||
run: go env
|
|
||||||
#- name: Install Go
|
|
||||||
# uses: actions/setup-go@v5
|
|
||||||
# with:
|
|
||||||
# go-version: '1.23'
|
|
||||||
# cache: true
|
|
||||||
- name: Restore cached LLVM source
|
- name: Restore cached LLVM source
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
@@ -95,25 +85,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Restore Go cache
|
|
||||||
uses: actions/cache/restore@v4
|
|
||||||
with:
|
|
||||||
key: go-cache-v2
|
|
||||||
path: |
|
|
||||||
C:/Users/runneradmin/AppData/Local/go-build
|
|
||||||
C:/Users/runneradmin/go/pkg/mod
|
|
||||||
- name: Test TinyGo
|
|
||||||
shell: bash
|
|
||||||
run: make test GOTESTFLAGS="-short -run=TestBuild -v"
|
|
||||||
- name: Save Go cache
|
|
||||||
uses: actions/cache/save@v4
|
|
||||||
with:
|
|
||||||
key: go-cache-v2
|
|
||||||
path: |
|
|
||||||
C:/Users/runneradmin/AppData/Local/go-build
|
|
||||||
C:/Users/runneradmin/go/pkg/mod
|
|
||||||
- name: exit
|
|
||||||
run: command-does-not-exist
|
|
||||||
- name: Cache wasi-libc sysroot
|
- name: Cache wasi-libc sysroot
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
@@ -128,13 +99,16 @@ jobs:
|
|||||||
scoop install wasmtime@14.0.4
|
scoop install wasmtime@14.0.4
|
||||||
- name: make gen-device
|
- name: make gen-device
|
||||||
run: make -j3 gen-device
|
run: make -j3 gen-device
|
||||||
|
- name: Test TinyGo
|
||||||
|
shell: bash
|
||||||
|
run: make test GOTESTFLAGS="-short"
|
||||||
- name: Build TinyGo release tarball
|
- name: Build TinyGo release tarball
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make build/release -j4
|
run: make build/release -j4
|
||||||
- name: Make release artifact
|
- name: Make release artifact
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: build/release
|
working-directory: build/release
|
||||||
run: 7z -tzip a tinygo${{ steps.version.outputs.version }}.windows-amd64.zip tinygo
|
run: 7z -tzip a release.zip tinygo
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
# Note: this release artifact is double-zipped, see:
|
# Note: this release artifact is double-zipped, see:
|
||||||
# https://github.com/actions/upload-artifact/issues/39
|
# https://github.com/actions/upload-artifact/issues/39
|
||||||
@@ -144,8 +118,8 @@ jobs:
|
|||||||
# We're doing the former here, to keep artifact uploads fast.
|
# We're doing the former here, to keep artifact uploads fast.
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ steps.version.outputs.version }}
|
name: windows-amd64-double-zipped
|
||||||
path: build/release/tinygo${{ steps.version.outputs.version }}.windows-amd64.zip
|
path: build/release/release.zip
|
||||||
|
|
||||||
smoke-test-windows:
|
smoke-test-windows:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
@@ -174,12 +148,12 @@ jobs:
|
|||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
|
name: windows-amd64-double-zipped
|
||||||
path: build/
|
path: build/
|
||||||
- name: Unzip TinyGo build
|
- name: Unzip TinyGo build
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: build
|
working-directory: build
|
||||||
run: 7z x tinygo*.windows-amd64.zip -r
|
run: 7z x release.zip -r
|
||||||
- name: Smoke tests
|
- name: Smoke tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make smoketest TINYGO=$(PWD)/build/tinygo/bin/tinygo
|
run: make smoketest TINYGO=$(PWD)/build/tinygo/bin/tinygo
|
||||||
@@ -204,12 +178,12 @@ jobs:
|
|||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
|
name: windows-amd64-double-zipped
|
||||||
path: build/
|
path: build/
|
||||||
- name: Unzip TinyGo build
|
- name: Unzip TinyGo build
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: build
|
working-directory: build
|
||||||
run: 7z x tinygo*.windows-amd64.zip -r
|
run: 7z x release.zip -r
|
||||||
- name: Test stdlib packages
|
- name: Test stdlib packages
|
||||||
run: make tinygo-test TINYGO=$(PWD)/build/tinygo/bin/tinygo
|
run: make tinygo-test TINYGO=$(PWD)/build/tinygo/bin/tinygo
|
||||||
|
|
||||||
@@ -240,11 +214,11 @@ jobs:
|
|||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
|
name: windows-amd64-double-zipped
|
||||||
path: build/
|
path: build/
|
||||||
- name: Unzip TinyGo build
|
- name: Unzip TinyGo build
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: build
|
working-directory: build
|
||||||
run: 7z x tinygo*.windows-amd64.zip -r
|
run: 7z x release.zip -r
|
||||||
- name: Test stdlib packages on wasip1
|
- name: Test stdlib packages on wasip1
|
||||||
run: make tinygo-test-wasip1-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo
|
run: make tinygo-test-wasip1-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo
|
||||||
|
|||||||
@@ -1,53 +1,3 @@
|
|||||||
0.34.0
|
|
||||||
---
|
|
||||||
* **general**
|
|
||||||
- fix `GOOS=wasip1` for `tinygo test`
|
|
||||||
- add `-C DIR` flag
|
|
||||||
- add initial documentation for project governance
|
|
||||||
- add `-ldflags='-extldflags=...'` support
|
|
||||||
- improve usage message with `tinygo help` and when passing invalid parameters
|
|
||||||
* **compiler**
|
|
||||||
- `builder`: remove environment variables when invoking Clang, to avoid the environment changing the behavior
|
|
||||||
- `builder`: check for the Go toolchain version used to compile TinyGo
|
|
||||||
- `cgo`: add `C.CBytes` implementation
|
|
||||||
- `compiler`: fix passing weirdly-padded structs as parameters to new goroutines
|
|
||||||
- `compiler`: support pragmas on generic functions
|
|
||||||
- `compiler`: do not let the slice buffer escape when casting a `[]byte` or `[]rune` to a string, to help escape analysis
|
|
||||||
- `compiler`: conform to the latest iteration of the wasm types proposal
|
|
||||||
- `loader`: don't panic when main package is not named 'main'
|
|
||||||
- `loader`: make sure we always return type checker errors even without type errors
|
|
||||||
- `transform`: optimize range over `[]byte(string)`
|
|
||||||
* **standard library**
|
|
||||||
- `crypto/x509`: add package stub to build crypto/x509 on macOS
|
|
||||||
- `machine/usb/adc/midi`: fix `PitchBend`
|
|
||||||
- `os`: add `Truncate` stub for baremetal
|
|
||||||
- `os`: add stubs for `os.File` deadlines
|
|
||||||
- `os`: add internal `net.newUnixFile` for the net package
|
|
||||||
- `runtime`: stub runtime_{Before,After}Exec for linkage
|
|
||||||
- `runtime`: randomize map accesses
|
|
||||||
- `runtime`: support `maps.Clone`
|
|
||||||
- `runtime`: add more fields to `MemStats`
|
|
||||||
- `runtime`: implement newcoro, coroswitch to support package iter
|
|
||||||
- `runtime`: disallow defer in interrupts
|
|
||||||
- `runtime`: add support for os/signal on Linux and MacOS
|
|
||||||
- `runtime`: add gc layout info for some basic types to help the precise GC
|
|
||||||
- `runtime`: bump GC mark stack size to avoid excessive heap rescans
|
|
||||||
* **targets**
|
|
||||||
- `darwin`: use Go standard library syscall package instead of a custom one
|
|
||||||
- `fe310`: support GPIO `PinInput`
|
|
||||||
- `mips`: fix compiler crash with GOMIPS=softfloat and defer
|
|
||||||
- `mips`: add big-endian (GOARCH=mips) support
|
|
||||||
- `mips`: use MIPS32 (instead of MIPS32R2) as the instruction set for wider compatibility
|
|
||||||
- `wasi`: add relative and absolute --dir options to wasmtime args
|
|
||||||
- `wasip2`: add wasmtime -S args to support network interfaces
|
|
||||||
- `wasm`: add `//go:wasmexport` support (for all WebAssembly targets)
|
|
||||||
- `wasm`: use precise instead of conservative GC for WebAssembly (including WASI)
|
|
||||||
- `wasm-unknown`: add bulk memory flags since basically every runtime has it now
|
|
||||||
* **boards**
|
|
||||||
- add RAKwireless RAK4631
|
|
||||||
- add WaveShare ESP-C3-32S-Kit
|
|
||||||
|
|
||||||
|
|
||||||
0.33.0
|
0.33.0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+23
-34
@@ -191,7 +191,7 @@ gen-device: gen-device-stm32
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
gen-device-avr:
|
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"; 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/
|
$(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/atmega src/device/avr/
|
||||||
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
|
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
|
||||||
@@ -263,7 +263,7 @@ endif
|
|||||||
.PHONY: wasi-libc
|
.PHONY: wasi-libc
|
||||||
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
||||||
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"; 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)
|
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
|
# Generate WASI syscall bindings
|
||||||
@@ -291,14 +291,15 @@ endif
|
|||||||
|
|
||||||
tinygo: ## Build the TinyGo compiler
|
tinygo: ## Build the TinyGo compiler
|
||||||
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
|
@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" .
|
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
|
test: wasi-libc check-nodejs-version
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -race -buildmode exe -tags "byollvm osusergo" .
|
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
|
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
||||||
TEST_PACKAGES_SLOW = \
|
TEST_PACKAGES_SLOW = \
|
||||||
compress/bzip2 \
|
compress/bzip2 \
|
||||||
crypto/dsa \
|
crypto/dsa \
|
||||||
|
crypto/ecdsa \
|
||||||
index/suffixarray \
|
index/suffixarray \
|
||||||
|
|
||||||
# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows
|
# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows
|
||||||
@@ -310,7 +311,6 @@ TEST_PACKAGES_FAST = \
|
|||||||
container/list \
|
container/list \
|
||||||
container/ring \
|
container/ring \
|
||||||
crypto/des \
|
crypto/des \
|
||||||
crypto/ecdsa \
|
|
||||||
crypto/elliptic \
|
crypto/elliptic \
|
||||||
crypto/md5 \
|
crypto/md5 \
|
||||||
crypto/rc4 \
|
crypto/rc4 \
|
||||||
@@ -319,6 +319,7 @@ TEST_PACKAGES_FAST = \
|
|||||||
crypto/sha512 \
|
crypto/sha512 \
|
||||||
database/sql/driver \
|
database/sql/driver \
|
||||||
debug/macho \
|
debug/macho \
|
||||||
|
embed \
|
||||||
embed/internal/embedtest \
|
embed/internal/embedtest \
|
||||||
encoding \
|
encoding \
|
||||||
encoding/ascii85 \
|
encoding/ascii85 \
|
||||||
@@ -342,6 +343,7 @@ TEST_PACKAGES_FAST = \
|
|||||||
math/cmplx \
|
math/cmplx \
|
||||||
net/http/internal/ascii \
|
net/http/internal/ascii \
|
||||||
net/mail \
|
net/mail \
|
||||||
|
net/textproto \
|
||||||
os \
|
os \
|
||||||
path \
|
path \
|
||||||
reflect \
|
reflect \
|
||||||
@@ -365,17 +367,17 @@ endif
|
|||||||
# archive/zip requires os.ReadAt, which is not yet supported on windows
|
# archive/zip requires os.ReadAt, which is not yet supported on windows
|
||||||
# bytes requires mmap
|
# bytes requires mmap
|
||||||
# compress/flate appears to hang on wasi
|
# compress/flate appears to hang on wasi
|
||||||
# crypto/aes fails on wasi, needs panic()/recover()
|
# context requires recover(), which is not yet supported on wasi
|
||||||
|
# crypto/aes requires recover(), which is not yet supported on wasi
|
||||||
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
|
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
|
||||||
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
|
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
|
||||||
|
# go/build/constraint requires recover(), which is not yet supported on wasi
|
||||||
# image requires recover(), which is not yet supported on wasi
|
# image requires recover(), which is not yet supported on wasi
|
||||||
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
|
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
|
||||||
# mime: fail on wasi; neds panic()/recover()
|
# mime exits with "bufio.Scanner: Read returned impossible count" on wasi
|
||||||
# mime/multipart: needs wasip1 syscall.FDFLAG_NONBLOCK
|
# mime/multipart has a nil pointer dereference (stack overflow?)
|
||||||
# mime/quotedprintable requires syscall.Faccessat
|
# mime/quotedprintable requires syscall.Faccessat
|
||||||
# net/mail: needs wasip1 syscall.FDFLAG_NONBLOCK
|
# regexp/syntax requires recover() which is not yet supported on wasi
|
||||||
# net/ntextproto: needs wasip1 syscall.FDFLAG_NONBLOCK
|
|
||||||
# regexp/syntax: fails on wasip1; needs panic()/recover()
|
|
||||||
# strconv requires recover() which is not yet supported on wasi
|
# strconv requires recover() which is not yet supported on wasi
|
||||||
# text/tabwriter requires recover(), which is not yet supported on wasi
|
# text/tabwriter requires recover(), which is not yet supported on wasi
|
||||||
# text/template/parse requires recover(), which is not yet supported on wasi
|
# text/template/parse requires recover(), which is not yet supported on wasi
|
||||||
@@ -385,18 +387,18 @@ endif
|
|||||||
TEST_PACKAGES_LINUX := \
|
TEST_PACKAGES_LINUX := \
|
||||||
archive/zip \
|
archive/zip \
|
||||||
compress/flate \
|
compress/flate \
|
||||||
|
context \
|
||||||
crypto/aes \
|
crypto/aes \
|
||||||
crypto/hmac \
|
crypto/hmac \
|
||||||
debug/dwarf \
|
debug/dwarf \
|
||||||
debug/plan9obj \
|
debug/plan9obj \
|
||||||
|
go/build/constraint \
|
||||||
image \
|
image \
|
||||||
io/ioutil \
|
io/ioutil \
|
||||||
mime \
|
mime \
|
||||||
mime/multipart \
|
mime/multipart \
|
||||||
mime/quotedprintable \
|
mime/quotedprintable \
|
||||||
net \
|
net \
|
||||||
net/mail \
|
|
||||||
net/textproto \
|
|
||||||
os/user \
|
os/user \
|
||||||
regexp/syntax \
|
regexp/syntax \
|
||||||
strconv \
|
strconv \
|
||||||
@@ -407,8 +409,14 @@ TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
|
|||||||
|
|
||||||
TEST_PACKAGES_WINDOWS := \
|
TEST_PACKAGES_WINDOWS := \
|
||||||
compress/flate \
|
compress/flate \
|
||||||
|
context \
|
||||||
|
crypto/aes \
|
||||||
crypto/hmac \
|
crypto/hmac \
|
||||||
|
go/build/constraint \
|
||||||
|
mime \
|
||||||
|
mime/multipart \
|
||||||
os/user \
|
os/user \
|
||||||
|
regexp/syntax \
|
||||||
strconv \
|
strconv \
|
||||||
text/template/parse \
|
text/template/parse \
|
||||||
$(nil)
|
$(nil)
|
||||||
@@ -503,17 +511,8 @@ tinygo-baremetal:
|
|||||||
# regression test for #2666: e.g. encoding/hex must pass on baremetal
|
# regression test for #2666: e.g. encoding/hex must pass on baremetal
|
||||||
$(TINYGO) test -target cortex-m-qemu encoding/hex
|
$(TINYGO) test -target cortex-m-qemu encoding/hex
|
||||||
|
|
||||||
.PHONY: testchdir
|
|
||||||
testchdir:
|
|
||||||
# test 'build' command with{,out} -C argument
|
|
||||||
$(TINYGO) build -C tests/testing/chdir chdir.go && rm tests/testing/chdir/chdir
|
|
||||||
$(TINYGO) build ./tests/testing/chdir/chdir.go && rm chdir
|
|
||||||
# test 'run' command with{,out} -C argument
|
|
||||||
EXPECT_DIR=$(PWD)/tests/testing/chdir $(TINYGO) run -C tests/testing/chdir chdir.go
|
|
||||||
EXPECT_DIR=$(PWD) $(TINYGO) run ./tests/testing/chdir/chdir.go
|
|
||||||
|
|
||||||
.PHONY: smoketest
|
.PHONY: smoketest
|
||||||
smoketest: testchdir
|
smoketest:
|
||||||
$(TINYGO) version
|
$(TINYGO) version
|
||||||
$(TINYGO) targets > /dev/null
|
$(TINYGO) targets > /dev/null
|
||||||
# regression test for #2892
|
# regression test for #2892
|
||||||
@@ -835,20 +834,12 @@ ifneq ($(XTENSA), 0)
|
|||||||
$(TINYGO) build -size short -o test.bin -target mch2022 examples/machinetest
|
$(TINYGO) build -size short -o test.bin -target mch2022 examples/machinetest
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
endif
|
endif
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit examples/blinky1
|
|
||||||
@$(MD5SUM) test.bin
|
|
||||||
$(TINYGO) build -size short -o test.bin -target=qtpy-esp32c3 examples/machinetest
|
$(TINYGO) build -size short -o test.bin -target=qtpy-esp32c3 examples/machinetest
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/machinetest
|
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/machinetest
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/machinetest
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/machinetest
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32-c3-devkit-rust-1 examples/blinky1
|
|
||||||
@$(MD5SUM) test.bin
|
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/blinky1
|
|
||||||
@$(MD5SUM) test.bin
|
|
||||||
$(TINYGO) build -size short -o test.bin -target=makerfabs-esp32c3spi35 examples/machinetest
|
|
||||||
@$(MD5SUM) test.bin
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
||||||
@@ -926,7 +917,6 @@ endif
|
|||||||
@cp -rp lib/musl/src/env build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/env build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/errno build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/errno build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/exit build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/exit build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/fcntl build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/include build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/include build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/legacy build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/legacy build/release/tinygo/lib/musl/src
|
||||||
@@ -942,7 +932,6 @@ endif
|
|||||||
@cp -rp lib/musl/src/thread build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/thread build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/time build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/time build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/unistd build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/unistd build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/process build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/def-include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
@cp -rp lib/mingw-w64/mingw-w64-crt/def-include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
TinyGo Team Members
|
|
||||||
===================
|
|
||||||
|
|
||||||
The team of humans who maintain TinyGo.
|
|
||||||
|
|
||||||
* **Purpose**: To maintain the community, code, documentation, and tools for the TinyGo compiler.
|
|
||||||
* **Board**: The group of people who share responsibility for key decisions for the TinyGo organization.
|
|
||||||
* **Majority Voting**: The board makes decisions by majority vote.
|
|
||||||
* **Membership**: The board elects its own members.
|
|
||||||
* **Do-ocracy**: Those who step forward to do a given task propose how it should be done. Then other interested people can make comments.
|
|
||||||
* **Proof of Work**: Power in decision-making is slightly weighted based on a participant's labor for the community.
|
|
||||||
* **Initiation**: We need to establish a procedure for how people join the team of maintainers.
|
|
||||||
* **Transparency**: Important information should be made publicly available, ideally in a way that allows for public comment.
|
|
||||||
* **Code of Conduct**: Participants agree to abide by the current project Code of Conduct.
|
|
||||||
|
|
||||||
## Members
|
|
||||||
|
|
||||||
* Ayke van Laethem (@aykevl)
|
|
||||||
* Daniel Esteban (@conejoninja)
|
|
||||||
* Ron Evans (@deadprogram)
|
|
||||||
* Damian Gryski (@dgryski)
|
|
||||||
* Masaaki Takasago (@sago35)
|
|
||||||
* Patricio Whittingslow (@soypat)
|
|
||||||
* Yurii Soldak (@ysoldak)
|
|
||||||
|
|
||||||
## Experimental
|
|
||||||
|
|
||||||
* **Monthly Meeting**: A monthly meeting for the team and any other interested participants.
|
|
||||||
Duration: 1 hour
|
|
||||||
Facilitation: @deadprogram
|
|
||||||
Schedule: See https://github.com/tinygo-org/tinygo/wiki/Meetings for more information
|
|
||||||
|
|
||||||
+16
-22
@@ -197,7 +197,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
ABI: config.ABI(),
|
ABI: config.ABI(),
|
||||||
GOOS: config.GOOS(),
|
GOOS: config.GOOS(),
|
||||||
GOARCH: config.GOARCH(),
|
GOARCH: config.GOARCH(),
|
||||||
BuildMode: config.BuildMode(),
|
|
||||||
CodeModel: config.CodeModel(),
|
CodeModel: config.CodeModel(),
|
||||||
RelocationModel: config.RelocationModel(),
|
RelocationModel: config.RelocationModel(),
|
||||||
SizeLevel: sizeLevel,
|
SizeLevel: sizeLevel,
|
||||||
@@ -650,13 +649,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
result.Binary = result.Executable // final file
|
result.Binary = result.Executable // final file
|
||||||
ldflags := append(config.LDFlags(), "-o", result.Executable)
|
ldflags := append(config.LDFlags(), "-o", result.Executable)
|
||||||
|
|
||||||
if config.Options.BuildMode == "c-shared" {
|
|
||||||
if !strings.HasPrefix(config.Triple(), "wasm32-") {
|
|
||||||
return result, fmt.Errorf("buildmode c-shared is only supported on wasm at the moment")
|
|
||||||
}
|
|
||||||
ldflags = append(ldflags, "--no-entry")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add compiler-rt dependency if needed. Usually this is a simple load from
|
// Add compiler-rt dependency if needed. Usually this is a simple load from
|
||||||
// a cache.
|
// a cache.
|
||||||
if config.Target.RTLib == "compiler-rt" {
|
if config.Target.RTLib == "compiler-rt" {
|
||||||
@@ -831,13 +823,19 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
args = append(args, "--asyncify")
|
args = append(args, "--asyncify")
|
||||||
}
|
}
|
||||||
|
|
||||||
inputFile := result.Binary
|
exeunopt := result.Executable
|
||||||
result.Binary = result.Executable + ".wasmopt"
|
|
||||||
|
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,
|
args = append(args,
|
||||||
opt,
|
opt,
|
||||||
"-g",
|
"-g",
|
||||||
inputFile,
|
exeunopt,
|
||||||
"--output", result.Binary,
|
"--output", result.Executable,
|
||||||
)
|
)
|
||||||
|
|
||||||
wasmopt := goenv.Get("WASMOPT")
|
wasmopt := goenv.Get("WASMOPT")
|
||||||
@@ -867,15 +865,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
// wasm-tools component embed -w wasi:cli/command
|
// wasm-tools component embed -w wasi:cli/command
|
||||||
// $$(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm
|
// $$(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm
|
||||||
componentEmbedInputFile := result.Binary
|
|
||||||
result.Binary = result.Executable + ".wasm-component-embed"
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"component",
|
"component",
|
||||||
"embed",
|
"embed",
|
||||||
"-w", witWorld,
|
"-w", witWorld,
|
||||||
witPackage,
|
witPackage,
|
||||||
componentEmbedInputFile,
|
result.Executable,
|
||||||
"-o", result.Binary,
|
"-o", result.Executable,
|
||||||
}
|
}
|
||||||
|
|
||||||
wasmtools := goenv.Get("WASMTOOLS")
|
wasmtools := goenv.Get("WASMTOOLS")
|
||||||
@@ -888,17 +884,15 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("`wasm-tools component embed` failed: %w", err)
|
return fmt.Errorf("wasm-tools failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// wasm-tools component new embedded.wasm -o component.wasm
|
// wasm-tools component new embedded.wasm -o component.wasm
|
||||||
componentNewInputFile := result.Binary
|
|
||||||
result.Binary = result.Executable + ".wasm-component-new"
|
|
||||||
args = []string{
|
args = []string{
|
||||||
"component",
|
"component",
|
||||||
"new",
|
"new",
|
||||||
componentNewInputFile,
|
result.Executable,
|
||||||
"-o", result.Binary,
|
"-o", result.Executable,
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Options.PrintCommands != nil {
|
if config.Options.PrintCommands != nil {
|
||||||
@@ -910,7 +904,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("`wasm-tools component new` failed: %w", err)
|
return fmt.Errorf("wasm-tools failed: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -75,3 +76,14 @@ func LookupCommand(name string) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", errors.New("none of these commands were found in your $PATH: " + strings.Join(commands[name], " "))
|
return "", errors.New("none of these commands were found in your $PATH: " + strings.Join(commands[name], " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func execCommand(name string, args ...string) error {
|
||||||
|
name, err := LookupCommand(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd := exec.Command(name, args...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|||||||
+4
-22
@@ -2,7 +2,6 @@ package builder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
@@ -24,37 +23,20 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
spec.OpenOCDCommands = options.OpenOCDCommands
|
spec.OpenOCDCommands = options.OpenOCDCommands
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version range supported by TinyGo.
|
major, minor, err := goenv.GetGorootVersion()
|
||||||
const minorMin = 19
|
|
||||||
const minorMax = 23
|
|
||||||
|
|
||||||
// Check that we support this Go toolchain version.
|
|
||||||
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
|
if major != 1 || minor < 19 || minor > 23 {
|
||||||
// Note: when this gets updated, also update the Go compatibility matrix:
|
// 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
|
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
|
||||||
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", gorootMajor, gorootMinor)
|
return nil, fmt.Errorf("requires go version 1.19 through 1.23, got go%d.%d", major, minor)
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the Go toolchain version isn't too new, if we haven't been
|
|
||||||
// compiled with the latest Go version.
|
|
||||||
// This may be a bit too aggressive: if the newer version doesn't change the
|
|
||||||
// Go language we will most likely be able to compile it.
|
|
||||||
buildMajor, buildMinor, _, err := goenv.Parse(runtime.Version())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if buildMajor != 1 || buildMinor < gorootMinor {
|
|
||||||
return nil, fmt.Errorf("cannot compile with Go toolchain version go%d.%d (TinyGo was built using toolchain version %s)", gorootMajor, gorootMinor, runtime.Version())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &compileopts.Config{
|
return &compileopts.Config{
|
||||||
Options: options,
|
Options: options,
|
||||||
Target: spec,
|
Target: spec,
|
||||||
GoMinorVersion: gorootMinor,
|
GoMinorVersion: minor,
|
||||||
TestConfig: options.TestConfig,
|
TestConfig: options.TestConfig,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-6
@@ -17,6 +17,14 @@ import (
|
|||||||
// concurrency or performance issues.
|
// concurrency or performance issues.
|
||||||
const jobRunnerDebug = false
|
const jobRunnerDebug = false
|
||||||
|
|
||||||
|
type jobState uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
jobStateQueued jobState = iota // not yet running
|
||||||
|
jobStateRunning // running
|
||||||
|
jobStateFinished // finished running
|
||||||
|
)
|
||||||
|
|
||||||
// compileJob is a single compiler job, comparable to a single Makefile target.
|
// compileJob is a single compiler job, comparable to a single Makefile target.
|
||||||
// It is used to orchestrate various compiler tasks that can be run in parallel
|
// It is used to orchestrate various compiler tasks that can be run in parallel
|
||||||
// but that have dependencies and thus have limitations in how they can be run.
|
// but that have dependencies and thus have limitations in how they can be run.
|
||||||
@@ -47,11 +55,12 @@ func dummyCompileJob(result string) *compileJob {
|
|||||||
// ordered as such in the job dependencies.
|
// ordered as such in the job dependencies.
|
||||||
func runJobs(job *compileJob, sema chan struct{}) error {
|
func runJobs(job *compileJob, sema chan struct{}) error {
|
||||||
if sema == nil {
|
if sema == nil {
|
||||||
// Have a default, if the semaphore isn't set. This is useful for tests.
|
// Have a default, if the semaphore isn't set. This is useful for
|
||||||
|
// tests.
|
||||||
sema = make(chan struct{}, runtime.NumCPU())
|
sema = make(chan struct{}, runtime.NumCPU())
|
||||||
}
|
}
|
||||||
if cap(sema) == 0 {
|
if cap(sema) == 0 {
|
||||||
return errors.New("cannot run 0 jobs at a time")
|
return errors.New("cannot 0 jobs at a time")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a slice of jobs to run, where all dependencies are run in order.
|
// Create a slice of jobs to run, where all dependencies are run in order.
|
||||||
@@ -72,10 +81,10 @@ func runJobs(job *compileJob, sema chan struct{}) error {
|
|||||||
|
|
||||||
waiting := make(map[*compileJob]map[*compileJob]struct{}, len(jobs))
|
waiting := make(map[*compileJob]map[*compileJob]struct{}, len(jobs))
|
||||||
dependents := make(map[*compileJob][]*compileJob, len(jobs))
|
dependents := make(map[*compileJob][]*compileJob, len(jobs))
|
||||||
compileJobs := make(map[*compileJob]int)
|
jidx := make(map[*compileJob]int)
|
||||||
var ready intHeap
|
var ready intHeap
|
||||||
for i, job := range jobs {
|
for i, job := range jobs {
|
||||||
compileJobs[job] = i
|
jidx[job] = i
|
||||||
if len(job.dependencies) == 0 {
|
if len(job.dependencies) == 0 {
|
||||||
// This job is ready to run.
|
// This job is ready to run.
|
||||||
ready.Push(i)
|
ready.Push(i)
|
||||||
@@ -96,7 +105,8 @@ func runJobs(job *compileJob, sema chan struct{}) error {
|
|||||||
// Create a channel to accept notifications of completion.
|
// Create a channel to accept notifications of completion.
|
||||||
doneChan := make(chan *compileJob)
|
doneChan := make(chan *compileJob)
|
||||||
|
|
||||||
// Send each job in the jobs slice to a worker, taking care of job dependencies.
|
// Send each job in the jobs slice to a worker, taking care of job
|
||||||
|
// dependencies.
|
||||||
numRunningJobs := 0
|
numRunningJobs := 0
|
||||||
var totalTime time.Duration
|
var totalTime time.Duration
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@@ -146,7 +156,7 @@ func runJobs(job *compileJob, sema chan struct{}) error {
|
|||||||
delete(wait, completed)
|
delete(wait, completed)
|
||||||
if len(wait) == 0 {
|
if len(wait) == 0 {
|
||||||
// This job is now ready to run.
|
// This job is now ready to run.
|
||||||
ready.Push(compileJobs[j])
|
ready.Push(jidx[j])
|
||||||
delete(waiting, j)
|
delete(waiting, j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,6 @@ var libMusl = Library{
|
|||||||
"env/*.c",
|
"env/*.c",
|
||||||
"errno/*.c",
|
"errno/*.c",
|
||||||
"exit/*.c",
|
"exit/*.c",
|
||||||
"fcntl/*.c",
|
|
||||||
"internal/defsysinfo.c",
|
"internal/defsysinfo.c",
|
||||||
"internal/libc.c",
|
"internal/libc.c",
|
||||||
"internal/syscall_ret.c",
|
"internal/syscall_ret.c",
|
||||||
@@ -129,7 +128,6 @@ var libMusl = Library{
|
|||||||
"mman/*.c",
|
"mman/*.c",
|
||||||
"math/*.c",
|
"math/*.c",
|
||||||
"multibyte/*.c",
|
"multibyte/*.c",
|
||||||
"signal/" + arch + "/*.s",
|
|
||||||
"signal/*.c",
|
"signal/*.c",
|
||||||
"stdio/*.c",
|
"stdio/*.c",
|
||||||
"string/*.c",
|
"string/*.c",
|
||||||
@@ -137,20 +135,12 @@ var libMusl = Library{
|
|||||||
"thread/*.c",
|
"thread/*.c",
|
||||||
"time/*.c",
|
"time/*.c",
|
||||||
"unistd/*.c",
|
"unistd/*.c",
|
||||||
"process/*.c",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if arch == "arm" {
|
if arch == "arm" {
|
||||||
// These files need to be added to the start for some reason.
|
// These files need to be added to the start for some reason.
|
||||||
globs = append([]string{"thread/arm/*.c"}, globs...)
|
globs = append([]string{"thread/arm/*.c"}, globs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if arch != "aarch64" && arch != "mips" {
|
|
||||||
//aarch64 and mips have no architecture specific code, either they
|
|
||||||
// are not supported or don't need any?
|
|
||||||
globs = append([]string{"process/" + arch + "/*.s"}, globs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
var sources []string
|
var sources []string
|
||||||
seenSources := map[string]struct{}{}
|
seenSources := map[string]struct{}{}
|
||||||
basepath := goenv.Get("TINYGOROOT") + "/lib/musl/src/"
|
basepath := goenv.Get("TINYGOROOT") + "/lib/musl/src/"
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ func TestBinarySize(t *testing.T) {
|
|||||||
// This is a small number of very diverse targets that we want to test.
|
// This is a small number of very diverse targets that we want to test.
|
||||||
tests := []sizeTest{
|
tests := []sizeTest{
|
||||||
// microcontrollers
|
// microcontrollers
|
||||||
{"hifive1b", "examples/echo", 4600, 280, 0, 2268},
|
{"hifive1b", "examples/echo", 4484, 280, 0, 2252},
|
||||||
{"microbit", "examples/serial", 2908, 388, 8, 2272},
|
{"microbit", "examples/serial", 2732, 388, 8, 2256},
|
||||||
{"wioterminal", "examples/pininterrupt", 6140, 1484, 116, 6832},
|
{"wioterminal", "examples/pininterrupt", 6016, 1484, 116, 6816},
|
||||||
|
|
||||||
// TODO: also check wasm. Right now this is difficult, because
|
// TODO: also check wasm. Right now this is difficult, because
|
||||||
// wasm binaries are run through wasm-opt and therefore the
|
// wasm binaries are run through wasm-opt and therefore the
|
||||||
|
|||||||
+6
-35
@@ -14,45 +14,16 @@ import (
|
|||||||
|
|
||||||
// runCCompiler invokes a C compiler with the given arguments.
|
// runCCompiler invokes a C compiler with the given arguments.
|
||||||
func runCCompiler(flags ...string) error {
|
func runCCompiler(flags ...string) error {
|
||||||
// Find the right command to run Clang.
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if hasBuiltinTools {
|
if hasBuiltinTools {
|
||||||
// Compile this with the internal Clang compiler.
|
// Compile this with the internal Clang compiler.
|
||||||
cmd = exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
|
cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
|
||||||
} else {
|
cmd.Stdout = os.Stdout
|
||||||
// Compile this with an external invocation of the Clang compiler.
|
cmd.Stderr = os.Stderr
|
||||||
name, err := LookupCommand("clang")
|
return cmd.Run()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmd = exec.Command(name, flags...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Stdout = os.Stdout
|
// Compile this with an external invocation of the Clang compiler.
|
||||||
cmd.Stderr = os.Stderr
|
return execCommand("clang", flags...)
|
||||||
|
|
||||||
// Make sure the command doesn't use any environmental variables.
|
|
||||||
// Most importantly, it should not use C_INCLUDE_PATH and the like.
|
|
||||||
cmd.Env = []string{}
|
|
||||||
|
|
||||||
// Let some environment variables through. One important one is the
|
|
||||||
// temporary directory, especially on Windows it looks like Clang breaks if
|
|
||||||
// the temporary directory has not been set.
|
|
||||||
// See: https://github.com/tinygo-org/tinygo/issues/4557
|
|
||||||
// Also see: https://github.com/llvm/llvm-project/blob/release/18.x/llvm/lib/Support/Unix/Path.inc#L1435
|
|
||||||
for _, env := range os.Environ() {
|
|
||||||
// We could parse the key and look it up in a map, but since there are
|
|
||||||
// only a few keys iterating through them is easier and maybe even
|
|
||||||
// faster.
|
|
||||||
for _, prefix := range []string{"TMPDIR=", "TMP=", "TEMP=", "TEMPDIR="} {
|
|
||||||
if strings.HasPrefix(env, prefix) {
|
|
||||||
cmd.Env = append(cmd.Env, env)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd.Run()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// link invokes a linker with the given name and flags.
|
// link invokes a linker with the given name and flags.
|
||||||
|
|||||||
+3
-10
@@ -162,13 +162,6 @@ func __GoBytes(unsafe.Pointer, uintptr) []byte
|
|||||||
func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func __CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
// Process extracts `import "C"` statements from the AST, parses the comment
|
// Process extracts `import "C"` statements from the AST, parses the comment
|
||||||
@@ -225,7 +218,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
switch decl := decl.(type) {
|
switch decl := decl.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
switch decl.Name.Name {
|
switch decl.Name.Name {
|
||||||
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes", "CBytes", "__CBytes":
|
case "CString", "GoString", "GoStringN", "__GoStringN", "GoBytes", "__GoBytes":
|
||||||
// Adjust the name to have a "C." prefix so it is correctly
|
// Adjust the name to have a "C." prefix so it is correctly
|
||||||
// resolved.
|
// resolved.
|
||||||
decl.Name.Name = "C." + decl.Name.Name
|
decl.Name.Name = "C." + decl.Name.Name
|
||||||
@@ -1148,7 +1141,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
|
|||||||
if alias := cgoAliases["C."+name]; alias != "" {
|
if alias := cgoAliases["C."+name]; alias != "" {
|
||||||
return alias
|
return alias
|
||||||
}
|
}
|
||||||
node := f.getASTDeclNode(name, found)
|
node := f.getASTDeclNode(name, found, iscall)
|
||||||
if node, ok := node.(*ast.FuncDecl); ok {
|
if node, ok := node.(*ast.FuncDecl); ok {
|
||||||
if !iscall {
|
if !iscall {
|
||||||
return node.Name.Name + "$funcaddr"
|
return node.Name.Name + "$funcaddr"
|
||||||
@@ -1160,7 +1153,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
|
|||||||
|
|
||||||
// getASTDeclNode will declare the given C AST node (if not already defined) and
|
// getASTDeclNode will declare the given C AST node (if not already defined) and
|
||||||
// returns it.
|
// returns it.
|
||||||
func (f *cgoFile) getASTDeclNode(name string, found clangCursor) ast.Node {
|
func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) ast.Node {
|
||||||
if node, ok := f.defined[name]; ok {
|
if node, ok := f.defined[name]; ok {
|
||||||
// Declaration was found in the current file, so return it immediately.
|
// Declaration was found in the current file, so return it immediately.
|
||||||
return node
|
return node
|
||||||
|
|||||||
+4
-136
@@ -54,72 +54,8 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseConst parses the given string as a C constant.
|
// parseConst parses the given string as a C constant.
|
||||||
func parseConst(pos token.Pos, fset *token.FileSet, value string, params []ast.Expr, callerPos token.Pos, f *cgoFile) (ast.Expr, *scanner.Error) {
|
func parseConst(pos token.Pos, fset *token.FileSet, value string) (ast.Expr, *scanner.Error) {
|
||||||
t := newTokenizer(pos, fset, value, f)
|
t := newTokenizer(pos, fset, value)
|
||||||
|
|
||||||
// If params is non-nil (could be a zero length slice), this const is
|
|
||||||
// actually a function-call like expression from another macro.
|
|
||||||
// This means we have to parse a string like "(a, b) (a+b)".
|
|
||||||
// We do this by parsing the parameters at the start and then treating the
|
|
||||||
// following like a normal constant expression.
|
|
||||||
if params != nil {
|
|
||||||
// Parse opening paren.
|
|
||||||
if t.curToken != token.LPAREN {
|
|
||||||
return nil, unexpectedToken(t, token.LPAREN)
|
|
||||||
}
|
|
||||||
t.Next()
|
|
||||||
|
|
||||||
// Parse parameters (identifiers) and closing paren.
|
|
||||||
var paramIdents []string
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
if i == 0 && t.curToken == token.RPAREN {
|
|
||||||
// No parameters, break early.
|
|
||||||
t.Next()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the parameter name.
|
|
||||||
if t.curToken != token.IDENT {
|
|
||||||
return nil, unexpectedToken(t, token.IDENT)
|
|
||||||
}
|
|
||||||
paramIdents = append(paramIdents, t.curValue)
|
|
||||||
t.Next()
|
|
||||||
|
|
||||||
// Read the next token: either a continuation (comma) or end of list
|
|
||||||
// (rparen).
|
|
||||||
if t.curToken == token.RPAREN {
|
|
||||||
// End of parameter list.
|
|
||||||
t.Next()
|
|
||||||
break
|
|
||||||
} else if t.curToken == token.COMMA {
|
|
||||||
// Comma, so there will be another parameter name.
|
|
||||||
t.Next()
|
|
||||||
} else {
|
|
||||||
return nil, &scanner.Error{
|
|
||||||
Pos: t.fset.Position(t.curPos),
|
|
||||||
Msg: "unexpected token " + t.curToken.String() + " inside macro parameters, expected ',' or ')'",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report an error if there is a mismatch in parameter length.
|
|
||||||
// The error is reported at the location of the closing paren from the
|
|
||||||
// caller location.
|
|
||||||
if len(params) != len(paramIdents) {
|
|
||||||
return nil, &scanner.Error{
|
|
||||||
Pos: t.fset.Position(callerPos),
|
|
||||||
Msg: fmt.Sprintf("unexpected number of parameters: expected %d, got %d", len(paramIdents), len(params)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign values to the parameters.
|
|
||||||
// These parameter names are closer in 'scope' than other identifiers so
|
|
||||||
// will be used first when parsing an identifier.
|
|
||||||
for i, name := range paramIdents {
|
|
||||||
t.params[name] = params[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expr, err := parseConstExpr(t, precedenceLowest)
|
expr, err := parseConstExpr(t, precedenceLowest)
|
||||||
t.Next()
|
t.Next()
|
||||||
if t.curToken != token.EOF {
|
if t.curToken != token.EOF {
|
||||||
@@ -160,68 +96,6 @@ func parseConstExpr(t *tokenizer, precedence int) (ast.Expr, *scanner.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseIdent(t *tokenizer) (ast.Expr, *scanner.Error) {
|
func parseIdent(t *tokenizer) (ast.Expr, *scanner.Error) {
|
||||||
// If the identifier is one of the parameters of this function-like macro,
|
|
||||||
// use the parameter value.
|
|
||||||
if val, ok := t.params[t.curValue]; ok {
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.f != nil {
|
|
||||||
// Check whether this identifier is actually a macro "call" with
|
|
||||||
// parameters. In that case, we should parse the parameters and pass it
|
|
||||||
// on to a new invocation of parseConst.
|
|
||||||
if t.peekToken == token.LPAREN {
|
|
||||||
if cursor, ok := t.f.names[t.curValue]; ok && t.f.isFunctionLikeMacro(cursor) {
|
|
||||||
// We know the current and peek tokens (the peek one is the '('
|
|
||||||
// token). So skip ahead until the current token is the first
|
|
||||||
// unknown token.
|
|
||||||
t.Next()
|
|
||||||
t.Next()
|
|
||||||
|
|
||||||
// Parse the list of parameters until ')' (rparen) is found.
|
|
||||||
params := []ast.Expr{}
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
if i == 0 && t.curToken == token.RPAREN {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
x, err := parseConstExpr(t, precedenceLowest)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
params = append(params, x)
|
|
||||||
t.Next()
|
|
||||||
if t.curToken == token.COMMA {
|
|
||||||
t.Next()
|
|
||||||
} else if t.curToken == token.RPAREN {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
return nil, &scanner.Error{
|
|
||||||
Pos: t.fset.Position(t.curPos),
|
|
||||||
Msg: "unexpected token " + t.curToken.String() + ", ',' or ')'",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate the macro value and use it as the identifier value.
|
|
||||||
rparen := t.curPos
|
|
||||||
pos, text := t.f.getMacro(cursor)
|
|
||||||
return parseConst(pos, t.fset, text, params, rparen, t.f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normally the name is something defined in the file (like another
|
|
||||||
// macro) which we get the declaration from using getASTDeclName.
|
|
||||||
// This ensures that names that are only referenced inside a macro are
|
|
||||||
// still getting defined.
|
|
||||||
if cursor, ok := t.f.names[t.curValue]; ok {
|
|
||||||
return &ast.Ident{
|
|
||||||
NamePos: t.curPos,
|
|
||||||
Name: t.f.getASTDeclName(t.curValue, cursor, false),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.f is nil during testing. This is a fallback.
|
|
||||||
return &ast.Ident{
|
return &ast.Ident{
|
||||||
NamePos: t.curPos,
|
NamePos: t.curPos,
|
||||||
Name: "C." + t.curValue,
|
Name: "C." + t.curValue,
|
||||||
@@ -290,25 +164,21 @@ func unexpectedToken(t *tokenizer, expected token.Token) *scanner.Error {
|
|||||||
|
|
||||||
// tokenizer reads C source code and converts it to Go tokens.
|
// tokenizer reads C source code and converts it to Go tokens.
|
||||||
type tokenizer struct {
|
type tokenizer struct {
|
||||||
f *cgoFile
|
|
||||||
curPos, peekPos token.Pos
|
curPos, peekPos token.Pos
|
||||||
fset *token.FileSet
|
fset *token.FileSet
|
||||||
curToken, peekToken token.Token
|
curToken, peekToken token.Token
|
||||||
curValue, peekValue string
|
curValue, peekValue string
|
||||||
buf string
|
buf string
|
||||||
params map[string]ast.Expr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTokenizer initializes a new tokenizer, positioned at the first token in
|
// newTokenizer initializes a new tokenizer, positioned at the first token in
|
||||||
// the string.
|
// the string.
|
||||||
func newTokenizer(start token.Pos, fset *token.FileSet, buf string, f *cgoFile) *tokenizer {
|
func newTokenizer(start token.Pos, fset *token.FileSet, buf string) *tokenizer {
|
||||||
t := &tokenizer{
|
t := &tokenizer{
|
||||||
f: f,
|
|
||||||
peekPos: start,
|
peekPos: start,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
buf: buf,
|
buf: buf,
|
||||||
peekToken: token.ILLEGAL,
|
peekToken: token.ILLEGAL,
|
||||||
params: make(map[string]ast.Expr),
|
|
||||||
}
|
}
|
||||||
// Parse the first two tokens (cur and peek).
|
// Parse the first two tokens (cur and peek).
|
||||||
t.Next()
|
t.Next()
|
||||||
@@ -360,7 +230,7 @@ func (t *tokenizer) Next() {
|
|||||||
t.peekValue = t.buf[:2]
|
t.peekValue = t.buf[:2]
|
||||||
t.buf = t.buf[2:]
|
t.buf = t.buf[2:]
|
||||||
return
|
return
|
||||||
case c == '(' || c == ')' || c == ',' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '&' || c == '|' || c == '^':
|
case c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '&' || c == '|' || c == '^':
|
||||||
// Single-character tokens.
|
// Single-character tokens.
|
||||||
// TODO: ++ (increment) and -- (decrement) operators.
|
// TODO: ++ (increment) and -- (decrement) operators.
|
||||||
switch c {
|
switch c {
|
||||||
@@ -368,8 +238,6 @@ func (t *tokenizer) Next() {
|
|||||||
t.peekToken = token.LPAREN
|
t.peekToken = token.LPAREN
|
||||||
case ')':
|
case ')':
|
||||||
t.peekToken = token.RPAREN
|
t.peekToken = token.RPAREN
|
||||||
case ',':
|
|
||||||
t.peekToken = token.COMMA
|
|
||||||
case '+':
|
case '+':
|
||||||
t.peekToken = token.ADD
|
t.peekToken = token.ADD
|
||||||
case '-':
|
case '-':
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ func TestParseConst(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
startPos := fset.AddFile("", -1, 1000).Pos(0)
|
startPos := fset.AddFile("", -1, 1000).Pos(0)
|
||||||
expr, err := parseConst(startPos, fset, tc.C, nil, token.NoPos, nil)
|
expr, err := parseConst(startPos, fset, tc.C)
|
||||||
s := "<invalid>"
|
s := "<invalid>"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !strings.HasPrefix(tc.Go, "error: ") {
|
if !strings.HasPrefix(tc.Go, "error: ") {
|
||||||
|
|||||||
+39
-59
@@ -63,7 +63,6 @@ long long tinygo_clang_getEnumConstantDeclValue(GoCXCursor c);
|
|||||||
CXType tinygo_clang_getEnumDeclIntegerType(GoCXCursor c);
|
CXType tinygo_clang_getEnumDeclIntegerType(GoCXCursor c);
|
||||||
unsigned tinygo_clang_Cursor_isAnonymous(GoCXCursor c);
|
unsigned tinygo_clang_Cursor_isAnonymous(GoCXCursor c);
|
||||||
unsigned tinygo_clang_Cursor_isBitField(GoCXCursor c);
|
unsigned tinygo_clang_Cursor_isBitField(GoCXCursor c);
|
||||||
unsigned tinygo_clang_Cursor_isMacroFunctionLike(GoCXCursor c);
|
|
||||||
|
|
||||||
int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
||||||
int tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
int tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
||||||
@@ -371,8 +370,45 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
|||||||
gen.Specs = append(gen.Specs, valueSpec)
|
gen.Specs = append(gen.Specs, valueSpec)
|
||||||
return gen, nil
|
return gen, nil
|
||||||
case C.CXCursor_MacroDefinition:
|
case C.CXCursor_MacroDefinition:
|
||||||
tokenPos, value := f.getMacro(c)
|
// Extract tokens from the Clang tokenizer.
|
||||||
expr, scannerError := parseConst(tokenPos, f.fset, value, nil, token.NoPos, f)
|
// See: https://stackoverflow.com/a/19074846/559350
|
||||||
|
sourceRange := C.tinygo_clang_getCursorExtent(c)
|
||||||
|
tu := C.tinygo_clang_Cursor_getTranslationUnit(c)
|
||||||
|
var rawTokens *C.CXToken
|
||||||
|
var numTokens C.unsigned
|
||||||
|
C.clang_tokenize(tu, sourceRange, &rawTokens, &numTokens)
|
||||||
|
tokens := unsafe.Slice(rawTokens, numTokens)
|
||||||
|
// Convert this range of tokens back to source text.
|
||||||
|
// Ugly, but it works well enough.
|
||||||
|
sourceBuf := &bytes.Buffer{}
|
||||||
|
var startOffset int
|
||||||
|
for i, token := range tokens {
|
||||||
|
spelling := getString(C.clang_getTokenSpelling(tu, token))
|
||||||
|
location := C.clang_getTokenLocation(tu, token)
|
||||||
|
var tokenOffset C.unsigned
|
||||||
|
C.clang_getExpansionLocation(location, nil, nil, nil, &tokenOffset)
|
||||||
|
if i == 0 {
|
||||||
|
// The first token is the macro name itself.
|
||||||
|
// Skip it (after using its location).
|
||||||
|
startOffset = int(tokenOffset) + len(name)
|
||||||
|
} else {
|
||||||
|
// Later tokens are the macro contents.
|
||||||
|
for int(tokenOffset) > (startOffset + sourceBuf.Len()) {
|
||||||
|
// Pad the source text with whitespace (that must have been
|
||||||
|
// present in the original source as well).
|
||||||
|
sourceBuf.WriteByte(' ')
|
||||||
|
}
|
||||||
|
sourceBuf.WriteString(spelling)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
C.clang_disposeTokens(tu, rawTokens, numTokens)
|
||||||
|
value := sourceBuf.String()
|
||||||
|
// Try to convert this #define into a Go constant expression.
|
||||||
|
tokenPos := token.NoPos
|
||||||
|
if pos != token.NoPos {
|
||||||
|
tokenPos = pos + token.Pos(len(name))
|
||||||
|
}
|
||||||
|
expr, scannerError := parseConst(tokenPos, f.fset, value)
|
||||||
if scannerError != nil {
|
if scannerError != nil {
|
||||||
f.errors = append(f.errors, *scannerError)
|
f.errors = append(f.errors, *scannerError)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -452,62 +488,6 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether this is a macro that's also function-like, like this:
|
|
||||||
//
|
|
||||||
// #define add(a, b) (a+b)
|
|
||||||
func (f *cgoFile) isFunctionLikeMacro(c clangCursor) bool {
|
|
||||||
if C.tinygo_clang_getCursorKind(c) != C.CXCursor_MacroDefinition {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return C.tinygo_clang_Cursor_isMacroFunctionLike(c) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the macro value: the position in the source file and the string value of
|
|
||||||
// the macro.
|
|
||||||
func (f *cgoFile) getMacro(c clangCursor) (pos token.Pos, value string) {
|
|
||||||
// Extract tokens from the Clang tokenizer.
|
|
||||||
// See: https://stackoverflow.com/a/19074846/559350
|
|
||||||
sourceRange := C.tinygo_clang_getCursorExtent(c)
|
|
||||||
tu := C.tinygo_clang_Cursor_getTranslationUnit(c)
|
|
||||||
var rawTokens *C.CXToken
|
|
||||||
var numTokens C.unsigned
|
|
||||||
C.clang_tokenize(tu, sourceRange, &rawTokens, &numTokens)
|
|
||||||
tokens := unsafe.Slice(rawTokens, numTokens)
|
|
||||||
defer C.clang_disposeTokens(tu, rawTokens, numTokens)
|
|
||||||
|
|
||||||
// Convert this range of tokens back to source text.
|
|
||||||
// Ugly, but it works well enough.
|
|
||||||
sourceBuf := &bytes.Buffer{}
|
|
||||||
var startOffset int
|
|
||||||
for i, token := range tokens {
|
|
||||||
spelling := getString(C.clang_getTokenSpelling(tu, token))
|
|
||||||
location := C.clang_getTokenLocation(tu, token)
|
|
||||||
var tokenOffset C.unsigned
|
|
||||||
C.clang_getExpansionLocation(location, nil, nil, nil, &tokenOffset)
|
|
||||||
if i == 0 {
|
|
||||||
// The first token is the macro name itself.
|
|
||||||
// Skip it (after using its location).
|
|
||||||
startOffset = int(tokenOffset)
|
|
||||||
} else {
|
|
||||||
// Later tokens are the macro contents.
|
|
||||||
for int(tokenOffset) > (startOffset + sourceBuf.Len()) {
|
|
||||||
// Pad the source text with whitespace (that must have been
|
|
||||||
// present in the original source as well).
|
|
||||||
sourceBuf.WriteByte(' ')
|
|
||||||
}
|
|
||||||
sourceBuf.WriteString(spelling)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value = sourceBuf.String()
|
|
||||||
|
|
||||||
// Obtain the position of this token. This is the position of the first
|
|
||||||
// character in the 'value' string and is used to report errors at the
|
|
||||||
// correct location in the source file.
|
|
||||||
pos = f.getCursorPosition(c)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getString(clangString C.CXString) (s string) {
|
func getString(clangString C.CXString) (s string) {
|
||||||
rawString := C.clang_getCString(clangString)
|
rawString := C.clang_getCString(clangString)
|
||||||
s = C.GoString(rawString)
|
s = C.GoString(rawString)
|
||||||
|
|||||||
@@ -84,7 +84,3 @@ unsigned tinygo_clang_Cursor_isAnonymous(CXCursor c) {
|
|||||||
unsigned tinygo_clang_Cursor_isBitField(CXCursor c) {
|
unsigned tinygo_clang_Cursor_isBitField(CXCursor c) {
|
||||||
return clang_Cursor_isBitField(c);
|
return clang_Cursor_isBitField(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned tinygo_clang_Cursor_isMacroFunctionLike(CXCursor c) {
|
|
||||||
return clang_Cursor_isMacroFunctionLike(c);
|
|
||||||
}
|
|
||||||
|
|||||||
Vendored
-7
@@ -24,13 +24,6 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func C.__CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func C.CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
C.char uint8
|
C.char uint8
|
||||||
C.schar int8
|
C.schar int8
|
||||||
|
|||||||
Vendored
-16
@@ -3,26 +3,10 @@ package main
|
|||||||
/*
|
/*
|
||||||
#define foo 3
|
#define foo 3
|
||||||
#define bar foo
|
#define bar foo
|
||||||
|
|
||||||
#define unreferenced 4
|
|
||||||
#define referenced unreferenced
|
|
||||||
|
|
||||||
#define fnlike() 5
|
|
||||||
#define fnlike_val fnlike()
|
|
||||||
#define square(n) (n*n)
|
|
||||||
#define square_val square(20)
|
|
||||||
#define add(a, b) (a + b)
|
|
||||||
#define add_val add(3, 5)
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Foo = C.foo
|
Foo = C.foo
|
||||||
Bar = C.bar
|
Bar = C.bar
|
||||||
|
|
||||||
Baz = C.referenced
|
|
||||||
|
|
||||||
fnlike = C.fnlike_val
|
|
||||||
square = C.square_val
|
|
||||||
add = C.add_val
|
|
||||||
)
|
)
|
||||||
|
|||||||
Vendored
-12
@@ -24,13 +24,6 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func C.__CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func C.CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
C.char uint8
|
C.char uint8
|
||||||
C.schar int8
|
C.schar int8
|
||||||
@@ -47,8 +40,3 @@ type (
|
|||||||
|
|
||||||
const C.foo = 3
|
const C.foo = 3
|
||||||
const C.bar = C.foo
|
const C.bar = C.foo
|
||||||
const C.unreferenced = 4
|
|
||||||
const C.referenced = C.unreferenced
|
|
||||||
const C.fnlike_val = 5
|
|
||||||
const C.square_val = (20 * 20)
|
|
||||||
const C.add_val = (3 + 5)
|
|
||||||
|
|||||||
Vendored
-8
@@ -26,11 +26,6 @@ import "C"
|
|||||||
// #warning another warning
|
// #warning another warning
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
// #define add(a, b) (a+b)
|
|
||||||
// #define add_toomuch add(1, 2, 3)
|
|
||||||
// #define add_toolittle add(1)
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
// Make sure that errors for the following lines won't change with future
|
// Make sure that errors for the following lines won't change with future
|
||||||
// additions to the CGo preamble.
|
// additions to the CGo preamble.
|
||||||
//
|
//
|
||||||
@@ -56,7 +51,4 @@ var (
|
|||||||
// constants passed by a command line parameter
|
// constants passed by a command line parameter
|
||||||
_ = C.SOME_PARAM_CONST_invalid
|
_ = C.SOME_PARAM_CONST_invalid
|
||||||
_ = C.SOME_PARAM_CONST_valid
|
_ = C.SOME_PARAM_CONST_valid
|
||||||
|
|
||||||
_ = C.add_toomuch
|
|
||||||
_ = C.add_toolittle
|
|
||||||
)
|
)
|
||||||
|
|||||||
Vendored
-11
@@ -7,8 +7,6 @@
|
|||||||
// testdata/errors.go:16:33: unexpected token ), expected end of expression
|
// testdata/errors.go:16:33: unexpected token ), expected end of expression
|
||||||
// testdata/errors.go:17:34: unexpected token ), expected end of expression
|
// testdata/errors.go:17:34: unexpected token ), expected end of expression
|
||||||
// -: unexpected token INT, expected end of expression
|
// -: unexpected token INT, expected end of expression
|
||||||
// testdata/errors.go:30:35: unexpected number of parameters: expected 2, got 3
|
|
||||||
// testdata/errors.go:31:31: unexpected number of parameters: expected 2, got 1
|
|
||||||
|
|
||||||
// Type checking errors after CGo processing:
|
// Type checking errors after CGo processing:
|
||||||
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as C.char value in variable declaration (overflows)
|
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as C.char value in variable declaration (overflows)
|
||||||
@@ -19,8 +17,6 @@
|
|||||||
// testdata/errors.go:114: undefined: C.SOME_CONST_b
|
// testdata/errors.go:114: undefined: C.SOME_CONST_b
|
||||||
// testdata/errors.go:116: undefined: C.SOME_CONST_startspace
|
// testdata/errors.go:116: undefined: C.SOME_CONST_startspace
|
||||||
// testdata/errors.go:119: undefined: C.SOME_PARAM_CONST_invalid
|
// testdata/errors.go:119: undefined: C.SOME_PARAM_CONST_invalid
|
||||||
// testdata/errors.go:122: undefined: C.add_toomuch
|
|
||||||
// testdata/errors.go:123: undefined: C.add_toolittle
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -48,13 +44,6 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func C.__CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func C.CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
C.char uint8
|
C.char uint8
|
||||||
C.schar int8
|
C.schar int8
|
||||||
|
|||||||
Vendored
-7
@@ -29,13 +29,6 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func C.__CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func C.CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
C.char uint8
|
C.char uint8
|
||||||
C.schar int8
|
C.schar int8
|
||||||
|
|||||||
Vendored
-7
@@ -24,13 +24,6 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func C.__CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func C.CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
C.char uint8
|
C.char uint8
|
||||||
C.schar int8
|
C.schar int8
|
||||||
|
|||||||
Vendored
-7
@@ -24,13 +24,6 @@ func C.GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
return C.__GoBytes(ptr, uintptr(length))
|
return C.__GoBytes(ptr, uintptr(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname C.__CBytes runtime.cgo_CBytes
|
|
||||||
func C.__CBytes([]byte) unsafe.Pointer
|
|
||||||
|
|
||||||
func C.CBytes(b []byte) unsafe.Pointer {
|
|
||||||
return C.__CBytes(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
C.char uint8
|
C.char uint8
|
||||||
C.schar int8
|
C.schar int8
|
||||||
|
|||||||
@@ -33,17 +33,6 @@ func (c *Config) CPU() string {
|
|||||||
return c.Target.CPU
|
return c.Target.CPU
|
||||||
}
|
}
|
||||||
|
|
||||||
// The current build mode (like the `-buildmode` command line flag).
|
|
||||||
func (c *Config) BuildMode() string {
|
|
||||||
if c.Options.BuildMode != "" {
|
|
||||||
return c.Options.BuildMode
|
|
||||||
}
|
|
||||||
if c.Target.BuildMode != "" {
|
|
||||||
return c.Target.BuildMode
|
|
||||||
}
|
|
||||||
return "default"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Features returns a list of features this CPU supports. For example, for a
|
// Features returns a list of features this CPU supports. For example, for a
|
||||||
// RISC-V processor, that could be "+a,+c,+m". For many targets, an empty list
|
// RISC-V processor, that could be "+a,+c,+m". For many targets, an empty list
|
||||||
// will be returned.
|
// will be returned.
|
||||||
@@ -406,8 +395,6 @@ func (c *Config) LDFlags() []string {
|
|||||||
if c.Target.LinkerScript != "" {
|
if c.Target.LinkerScript != "" {
|
||||||
ldflags = append(ldflags, "-T", c.Target.LinkerScript)
|
ldflags = append(ldflags, "-T", c.Target.LinkerScript)
|
||||||
}
|
}
|
||||||
ldflags = append(ldflags, c.Options.ExtLDFlags...)
|
|
||||||
|
|
||||||
return ldflags
|
return ldflags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validBuildModeOptions = []string{"default", "c-shared"}
|
|
||||||
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
|
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
|
||||||
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
|
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
|
||||||
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
|
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
|
||||||
@@ -27,7 +26,6 @@ type Options struct {
|
|||||||
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
|
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
|
||||||
Directory string // working dir, leave it unset to use the current working dir
|
Directory string // working dir, leave it unset to use the current working dir
|
||||||
Target string
|
Target string
|
||||||
BuildMode string // -buildmode flag
|
|
||||||
Opt string
|
Opt string
|
||||||
GC string
|
GC string
|
||||||
PanicStrategy string
|
PanicStrategy string
|
||||||
@@ -58,19 +56,10 @@ type Options struct {
|
|||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
WITPackage string // pass through to wasm-tools component embed invocation
|
WITPackage string // pass through to wasm-tools component embed invocation
|
||||||
WITWorld string // pass through to wasm-tools component embed -w option
|
WITWorld string // pass through to wasm-tools component embed -w option
|
||||||
ExtLDFlags []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||||
func (o *Options) Verify() error {
|
func (o *Options) Verify() error {
|
||||||
if o.BuildMode != "" {
|
|
||||||
valid := isInArray(validBuildModeOptions, o.BuildMode)
|
|
||||||
if !valid {
|
|
||||||
return fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,
|
|
||||||
o.BuildMode,
|
|
||||||
strings.Join(validBuildModeOptions, ", "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if o.GC != "" {
|
if o.GC != "" {
|
||||||
valid := isInArray(validGCOptions, o.GC)
|
valid := isInArray(validGCOptions, o.GC)
|
||||||
if !valid {
|
if !valid {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ type TargetSpec struct {
|
|||||||
GOARCH string `json:"goarch,omitempty"`
|
GOARCH string `json:"goarch,omitempty"`
|
||||||
SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc)
|
SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc)
|
||||||
BuildTags []string `json:"build-tags,omitempty"`
|
BuildTags []string `json:"build-tags,omitempty"`
|
||||||
BuildMode string `json:"buildmode,omitempty"` // default build mode (if nothing specified)
|
|
||||||
GC string `json:"gc,omitempty"`
|
GC string `json:"gc,omitempty"`
|
||||||
Scheduler string `json:"scheduler,omitempty"`
|
Scheduler string `json:"scheduler,omitempty"`
|
||||||
Serial string `json:"serial,omitempty"` // which serial output to use (uart, usb, none)
|
Serial string `json:"serial,omitempty"` // which serial output to use (uart, usb, none)
|
||||||
@@ -391,8 +390,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
)
|
)
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/runtime/os_darwin.c",
|
"src/runtime/os_darwin.c",
|
||||||
"src/runtime/runtime_unix.c",
|
"src/runtime/runtime_unix.c")
|
||||||
"src/runtime/signal.c")
|
|
||||||
case "linux":
|
case "linux":
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.RTLib = "compiler-rt"
|
spec.RTLib = "compiler-rt"
|
||||||
@@ -413,8 +411,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
|
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
|
||||||
}
|
}
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/runtime/runtime_unix.c",
|
"src/runtime/runtime_unix.c")
|
||||||
"src/runtime/signal.c")
|
|
||||||
case "windows":
|
case "windows":
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "mingw-w64"
|
spec.Libc = "mingw-w64"
|
||||||
@@ -452,7 +449,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
"--stack-first",
|
"--stack-first",
|
||||||
"--no-demangle",
|
"--no-demangle",
|
||||||
)
|
)
|
||||||
spec.Emulator = "wasmtime run --dir={tmpDir}::/tmp {}"
|
spec.Emulator = "wasmtime --dir={tmpDir}::/tmp {}"
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/runtime/asm_tinygowasm.S",
|
"src/runtime/asm_tinygowasm.S",
|
||||||
"src/internal/task/task_asyncify_wasm.S",
|
"src/internal/task/task_asyncify_wasm.S",
|
||||||
|
|||||||
+3
-13
@@ -17,7 +17,6 @@ import (
|
|||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||||
"github.com/tinygo-org/tinygo/loader"
|
"github.com/tinygo-org/tinygo/loader"
|
||||||
"github.com/tinygo-org/tinygo/src/tinygo"
|
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
@@ -45,7 +44,6 @@ type Config struct {
|
|||||||
ABI string
|
ABI string
|
||||||
GOOS string
|
GOOS string
|
||||||
GOARCH string
|
GOARCH string
|
||||||
BuildMode string
|
|
||||||
CodeModel string
|
CodeModel string
|
||||||
RelocationModel string
|
RelocationModel string
|
||||||
SizeLevel int
|
SizeLevel int
|
||||||
@@ -1386,11 +1384,6 @@ func (b *builder) createFunction() {
|
|||||||
b.llvmFn.SetLinkage(llvm.InternalLinkage)
|
b.llvmFn.SetLinkage(llvm.InternalLinkage)
|
||||||
b.createFunction()
|
b.createFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create wrapper function that can be called externally.
|
|
||||||
if b.info.wasmExport != "" {
|
|
||||||
b.createWasmExport()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// posser is an interface that's implemented by both ssa.Value and
|
// posser is an interface that's implemented by both ssa.Value and
|
||||||
@@ -1681,10 +1674,6 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
result = b.CreateSelect(cmp, result, arg, "")
|
result = b.CreateSelect(cmp, result, arg, "")
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
case "panic":
|
|
||||||
// This is rare, but happens in "defer panic()".
|
|
||||||
b.createRuntimeInvoke("_panic", argValues, "")
|
|
||||||
return llvm.Value{}, nil
|
|
||||||
case "print", "println":
|
case "print", "println":
|
||||||
for i, value := range argValues {
|
for i, value := range argValues {
|
||||||
if i >= 1 && callName == "println" {
|
if i >= 1 && callName == "println" {
|
||||||
@@ -1870,9 +1859,10 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
}
|
}
|
||||||
return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil
|
return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil
|
||||||
case name == "runtime.panicStrategy":
|
case name == "runtime.panicStrategy":
|
||||||
|
// These constants are defined in src/runtime/panic.go.
|
||||||
panicStrategy := map[string]uint64{
|
panicStrategy := map[string]uint64{
|
||||||
"print": tinygo.PanicStrategyPrint,
|
"print": 1, // panicStrategyPrint
|
||||||
"trap": tinygo.PanicStrategyTrap,
|
"trap": 2, // panicStrategyTrap
|
||||||
}[b.Config.PanicStrategy]
|
}[b.Config.PanicStrategy]
|
||||||
return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
|
return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
|
||||||
case name == "runtime/interrupt.New":
|
case name == "runtime/interrupt.New":
|
||||||
|
|||||||
+20
-253
@@ -7,7 +7,6 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
@@ -102,7 +101,7 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||||||
|
|
||||||
paramBundle := b.emitPointerPack(params)
|
paramBundle := b.emitPointerPack(params)
|
||||||
var stackSize llvm.Value
|
var stackSize llvm.Value
|
||||||
callee := b.createGoroutineStartWrapper(funcType, funcPtr, prefix, hasContext, false, instr.Pos())
|
callee := b.createGoroutineStartWrapper(funcType, funcPtr, prefix, hasContext, instr.Pos())
|
||||||
if b.AutomaticStackSize {
|
if b.AutomaticStackSize {
|
||||||
// The stack size is not known until after linking. Call a dummy
|
// The stack size is not known until after linking. Call a dummy
|
||||||
// function that will be replaced with a load from a special ELF
|
// function that will be replaced with a load from a special ELF
|
||||||
@@ -122,147 +121,6 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||||||
b.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.dataPtrType)}, "")
|
b.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.dataPtrType)}, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an exported wrapper function for functions with the //go:wasmexport
|
|
||||||
// pragma. This wrapper function is quite complex when the scheduler is enabled:
|
|
||||||
// it needs to start a new goroutine each time the exported function is called.
|
|
||||||
func (b *builder) createWasmExport() {
|
|
||||||
pos := b.info.wasmExportPos
|
|
||||||
if b.info.exported {
|
|
||||||
// //export really shouldn't be used anymore when //go:wasmexport is
|
|
||||||
// available, because //go:wasmexport is much better defined.
|
|
||||||
b.addError(pos, "cannot use //export and //go:wasmexport at the same time")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const suffix = "#wasmexport"
|
|
||||||
|
|
||||||
// Declare the exported function.
|
|
||||||
paramTypes := b.llvmFnType.ParamTypes()
|
|
||||||
exportedFnType := llvm.FunctionType(b.llvmFnType.ReturnType(), paramTypes[:len(paramTypes)-1], false)
|
|
||||||
exportedFn := llvm.AddFunction(b.mod, b.fn.RelString(nil)+suffix, exportedFnType)
|
|
||||||
b.addStandardAttributes(exportedFn)
|
|
||||||
llvmutil.AppendToGlobal(b.mod, "llvm.used", exportedFn)
|
|
||||||
exportedFn.AddFunctionAttr(b.ctx.CreateStringAttribute("wasm-export-name", b.info.wasmExport))
|
|
||||||
|
|
||||||
// Create a builder for this wrapper function.
|
|
||||||
builder := newBuilder(b.compilerContext, b.ctx.NewBuilder(), b.fn)
|
|
||||||
defer builder.Dispose()
|
|
||||||
|
|
||||||
// Define this function as a separate function in DWARF
|
|
||||||
if b.Debug {
|
|
||||||
if b.fn.Syntax() != nil {
|
|
||||||
// Create debug info file if needed.
|
|
||||||
pos := b.program.Fset.Position(pos)
|
|
||||||
builder.difunc = builder.attachDebugInfoRaw(b.fn, exportedFn, suffix, pos.Filename, pos.Line)
|
|
||||||
}
|
|
||||||
builder.setDebugLocation(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a single basic block inside of it.
|
|
||||||
bb := llvm.AddBasicBlock(exportedFn, "entry")
|
|
||||||
builder.SetInsertPointAtEnd(bb)
|
|
||||||
|
|
||||||
// Insert an assertion to make sure this //go:wasmexport function is not
|
|
||||||
// called at a time when it is not allowed (for example, before the runtime
|
|
||||||
// is initialized).
|
|
||||||
builder.createRuntimeCall("wasmExportCheckRun", nil, "")
|
|
||||||
|
|
||||||
if b.Scheduler == "none" {
|
|
||||||
// When the scheduler has been disabled, this is really trivial: just
|
|
||||||
// call the function.
|
|
||||||
params := exportedFn.Params()
|
|
||||||
params = append(params, llvm.ConstNull(b.dataPtrType)) // context parameter
|
|
||||||
retval := builder.CreateCall(b.llvmFnType, b.llvmFn, params, "")
|
|
||||||
if b.fn.Signature.Results() == nil {
|
|
||||||
builder.CreateRetVoid()
|
|
||||||
} else {
|
|
||||||
builder.CreateRet(retval)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// The scheduler is enabled, so we need to start a new goroutine, wait
|
|
||||||
// for it to complete, and read the result value.
|
|
||||||
|
|
||||||
// Build a function that looks like this:
|
|
||||||
//
|
|
||||||
// func foo#wasmexport(param0, param1, ..., paramN) {
|
|
||||||
// var state *stateStruct
|
|
||||||
//
|
|
||||||
// // 'done' must be explicitly initialized ('state' is not zeroed)
|
|
||||||
// state.done = false
|
|
||||||
//
|
|
||||||
// // store the parameters in the state object
|
|
||||||
// state.param0 = param0
|
|
||||||
// state.param1 = param1
|
|
||||||
// ...
|
|
||||||
// state.paramN = paramN
|
|
||||||
//
|
|
||||||
// // create a goroutine and push it to the runqueue
|
|
||||||
// task.start(uintptr(gowrapper), &state)
|
|
||||||
//
|
|
||||||
// // run the scheduler
|
|
||||||
// runtime.wasmExportRun(&state.done)
|
|
||||||
//
|
|
||||||
// // if there is a return value, load it and return
|
|
||||||
// return state.result
|
|
||||||
// }
|
|
||||||
|
|
||||||
hasReturn := b.fn.Signature.Results() != nil
|
|
||||||
|
|
||||||
// Build the state struct type.
|
|
||||||
// It stores the function parameters, the 'done' flag, and reserves
|
|
||||||
// space for a return value if needed.
|
|
||||||
stateFields := exportedFnType.ParamTypes()
|
|
||||||
numParams := len(stateFields)
|
|
||||||
stateFields = append(stateFields, b.ctx.Int1Type()) // 'done' field
|
|
||||||
if hasReturn {
|
|
||||||
stateFields = append(stateFields, b.llvmFnType.ReturnType())
|
|
||||||
}
|
|
||||||
stateStruct := b.ctx.StructType(stateFields, false)
|
|
||||||
|
|
||||||
// Allocate the state struct on the stack.
|
|
||||||
statePtr := builder.CreateAlloca(stateStruct, "status")
|
|
||||||
|
|
||||||
// Initialize the 'done' field.
|
|
||||||
doneGEP := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), uint64(numParams), false),
|
|
||||||
}, "done.gep")
|
|
||||||
builder.CreateStore(llvm.ConstNull(b.ctx.Int1Type()), doneGEP)
|
|
||||||
|
|
||||||
// Store all parameters in the state object.
|
|
||||||
for i, param := range exportedFn.Params() {
|
|
||||||
gep := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
|
|
||||||
}, "")
|
|
||||||
builder.CreateStore(param, gep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new goroutine and add it to the runqueue.
|
|
||||||
wrapper := b.createGoroutineStartWrapper(b.llvmFnType, b.llvmFn, "", false, true, pos)
|
|
||||||
stackSize := llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false)
|
|
||||||
taskStartFnType, taskStartFn := builder.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function))
|
|
||||||
builder.createCall(taskStartFnType, taskStartFn, []llvm.Value{wrapper, statePtr, stackSize, llvm.Undef(b.dataPtrType)}, "")
|
|
||||||
|
|
||||||
// Run the scheduler.
|
|
||||||
builder.createRuntimeCall("wasmExportRun", []llvm.Value{doneGEP}, "")
|
|
||||||
|
|
||||||
// Read the return value (if any) and return to the caller of the
|
|
||||||
// //go:wasmexport function.
|
|
||||||
if hasReturn {
|
|
||||||
gep := builder.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), uint64(numParams)+1, false),
|
|
||||||
}, "")
|
|
||||||
retval := builder.CreateLoad(b.llvmFnType.ReturnType(), gep, "retval")
|
|
||||||
builder.CreateRet(retval)
|
|
||||||
} else {
|
|
||||||
builder.CreateRetVoid()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// createGoroutineStartWrapper creates a wrapper for the task-based
|
// createGoroutineStartWrapper creates a wrapper for the task-based
|
||||||
// implementation of goroutines. For example, to call a function like this:
|
// implementation of goroutines. For example, to call a function like this:
|
||||||
//
|
//
|
||||||
@@ -286,7 +144,7 @@ func (b *builder) createWasmExport() {
|
|||||||
// to last parameter of the function) is used for this wrapper. If hasContext is
|
// to last parameter of the function) is used for this wrapper. If hasContext is
|
||||||
// false, the parameter bundle is assumed to have no context parameter and undef
|
// false, the parameter bundle is assumed to have no context parameter and undef
|
||||||
// is passed instead.
|
// is passed instead.
|
||||||
func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext, isWasmExport bool, pos token.Pos) llvm.Value {
|
func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext bool, pos token.Pos) llvm.Value {
|
||||||
var wrapper llvm.Value
|
var wrapper llvm.Value
|
||||||
|
|
||||||
b := &builder{
|
b := &builder{
|
||||||
@@ -304,18 +162,14 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
|
|||||||
if !fn.IsAFunction().IsNil() {
|
if !fn.IsAFunction().IsNil() {
|
||||||
// See whether this wrapper has already been created. If so, return it.
|
// See whether this wrapper has already been created. If so, return it.
|
||||||
name := fn.Name()
|
name := fn.Name()
|
||||||
wrapperName := name + "$gowrapper"
|
wrapper = c.mod.NamedFunction(name + "$gowrapper")
|
||||||
if isWasmExport {
|
|
||||||
wrapperName += "-wasmexport"
|
|
||||||
}
|
|
||||||
wrapper = c.mod.NamedFunction(wrapperName)
|
|
||||||
if !wrapper.IsNil() {
|
if !wrapper.IsNil() {
|
||||||
return llvm.ConstPtrToInt(wrapper, c.uintptrType)
|
return llvm.ConstPtrToInt(wrapper, c.uintptrType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the wrapper.
|
// Create the wrapper.
|
||||||
wrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.dataPtrType}, false)
|
wrapperType := llvm.FunctionType(c.ctx.VoidType(), []llvm.Type{c.dataPtrType}, false)
|
||||||
wrapper = llvm.AddFunction(c.mod, wrapperName, wrapperType)
|
wrapper = llvm.AddFunction(c.mod, name+"$gowrapper", wrapperType)
|
||||||
c.addStandardAttributes(wrapper)
|
c.addStandardAttributes(wrapper)
|
||||||
wrapper.SetLinkage(llvm.LinkOnceODRLinkage)
|
wrapper.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
wrapper.SetUnnamedAddr(true)
|
wrapper.SetUnnamedAddr(true)
|
||||||
@@ -345,110 +199,23 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
|
|||||||
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isWasmExport {
|
// Create the list of params for the call.
|
||||||
// Regular 'go' instruction.
|
paramTypes := fnType.ParamTypes()
|
||||||
|
if !hasContext {
|
||||||
|
paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter
|
||||||
|
}
|
||||||
|
params := b.emitPointerUnpack(wrapper.Param(0), paramTypes)
|
||||||
|
if !hasContext {
|
||||||
|
params = append(params, llvm.Undef(c.dataPtrType)) // add dummy context parameter
|
||||||
|
}
|
||||||
|
|
||||||
// Create the list of params for the call.
|
// Create the call.
|
||||||
paramTypes := fnType.ParamTypes()
|
b.CreateCall(fnType, fn, params, "")
|
||||||
if !hasContext {
|
|
||||||
paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
params := b.emitPointerUnpack(wrapper.Param(0), paramTypes)
|
if c.Scheduler == "asyncify" {
|
||||||
if !hasContext {
|
b.CreateCall(deadlockType, deadlock, []llvm.Value{
|
||||||
params = append(params, llvm.Undef(c.dataPtrType)) // add dummy context parameter
|
llvm.Undef(c.dataPtrType),
|
||||||
}
|
}, "")
|
||||||
|
|
||||||
// Create the call.
|
|
||||||
b.CreateCall(fnType, fn, params, "")
|
|
||||||
|
|
||||||
if c.Scheduler == "asyncify" {
|
|
||||||
b.CreateCall(deadlockType, deadlock, []llvm.Value{
|
|
||||||
llvm.Undef(c.dataPtrType),
|
|
||||||
}, "")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Goroutine started from a //go:wasmexport pragma.
|
|
||||||
// The function looks like this:
|
|
||||||
//
|
|
||||||
// func foo$gowrapper-wasmexport(state *stateStruct) {
|
|
||||||
// // load values
|
|
||||||
// param0 := state.params[0]
|
|
||||||
// param1 := state.params[1]
|
|
||||||
//
|
|
||||||
// // call wrapped functions
|
|
||||||
// result := foo(param0, param1, ...)
|
|
||||||
//
|
|
||||||
// // store result value (if there is any)
|
|
||||||
// state.result = result
|
|
||||||
//
|
|
||||||
// // finish exported function
|
|
||||||
// state.done = true
|
|
||||||
// runtime.wasmExportExit()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// The state object here looks like:
|
|
||||||
//
|
|
||||||
// struct state {
|
|
||||||
// param0
|
|
||||||
// param1
|
|
||||||
// param* // etc
|
|
||||||
// done bool
|
|
||||||
// result returnType
|
|
||||||
// }
|
|
||||||
|
|
||||||
returnType := fnType.ReturnType()
|
|
||||||
hasReturn := returnType != b.ctx.VoidType()
|
|
||||||
statePtr := wrapper.Param(0)
|
|
||||||
|
|
||||||
// Create the state struct (it must match the type in createWasmExport).
|
|
||||||
stateFields := fnType.ParamTypes()
|
|
||||||
numParams := len(stateFields) - 1
|
|
||||||
stateFields = stateFields[:numParams:numParams] // strip 'context' parameter
|
|
||||||
stateFields = append(stateFields, c.ctx.Int1Type()) // 'done' bool
|
|
||||||
if hasReturn {
|
|
||||||
stateFields = append(stateFields, returnType)
|
|
||||||
}
|
|
||||||
stateStruct := b.ctx.StructType(stateFields, false)
|
|
||||||
|
|
||||||
// Extract parameters from the state object, and call the function
|
|
||||||
// that's being wrapped.
|
|
||||||
var callParams []llvm.Value
|
|
||||||
for i := 0; i < numParams; i++ {
|
|
||||||
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
|
|
||||||
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
|
|
||||||
}, "")
|
|
||||||
param := b.CreateLoad(stateFields[i], gep, "")
|
|
||||||
callParams = append(callParams, param)
|
|
||||||
}
|
|
||||||
callParams = append(callParams, llvm.ConstNull(c.dataPtrType)) // add 'context' parameter
|
|
||||||
result := b.CreateCall(fnType, fn, callParams, "")
|
|
||||||
|
|
||||||
// Store the return value back into the shared state.
|
|
||||||
// Unlike regular goroutines, these special //go:wasmexport
|
|
||||||
// goroutines can return a value.
|
|
||||||
if hasReturn {
|
|
||||||
gep := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), uint64(numParams)+1, false),
|
|
||||||
}, "result.ptr")
|
|
||||||
b.CreateStore(result, gep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark this function as having finished executing.
|
|
||||||
// This is important so the runtime knows the exported function
|
|
||||||
// didn't block.
|
|
||||||
doneGEP := b.CreateInBoundsGEP(stateStruct, statePtr, []llvm.Value{
|
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), uint64(numParams), false),
|
|
||||||
}, "done.gep")
|
|
||||||
b.CreateStore(llvm.ConstInt(b.ctx.Int1Type(), 1, false), doneGEP)
|
|
||||||
|
|
||||||
// Call back into the runtime. This will exit the goroutine, switch
|
|
||||||
// back to the scheduler, which will in turn return from the
|
|
||||||
// //go:wasmexport function.
|
|
||||||
b.createRuntimeCall("wasmExportExit", nil, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -530,5 +297,5 @@ func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return a ptrtoint of the wrapper, not the function itself.
|
// Return a ptrtoint of the wrapper, not the function itself.
|
||||||
return llvm.ConstPtrToInt(wrapper, c.uintptrType)
|
return b.CreatePtrToInt(wrapper, c.uintptrType, "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||||||
|
|
||||||
// Create a new global of type runtime/interrupt.handle. Globals of this
|
// Create a new global of type runtime/interrupt.handle. Globals of this
|
||||||
// type are lowered in the interrupt lowering pass.
|
// type are lowered in the interrupt lowering pass.
|
||||||
// It must have an alignment of 1, otherwise LLVM thinks a ptrtoint of the
|
|
||||||
// global has the lower bits unset.
|
|
||||||
globalType := b.program.ImportedPackage("runtime/interrupt").Type("handle").Type()
|
globalType := b.program.ImportedPackage("runtime/interrupt").Type("handle").Type()
|
||||||
globalLLVMType := b.getLLVMType(globalType)
|
globalLLVMType := b.getLLVMType(globalType)
|
||||||
globalName := b.fn.Package().Pkg.Path() + "$interrupt" + strconv.FormatInt(id.Int64(), 10)
|
globalName := b.fn.Package().Pkg.Path() + "$interrupt" + strconv.FormatInt(id.Int64(), 10)
|
||||||
@@ -50,7 +48,6 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro
|
|||||||
global.SetVisibility(llvm.HiddenVisibility)
|
global.SetVisibility(llvm.HiddenVisibility)
|
||||||
global.SetGlobalConstant(true)
|
global.SetGlobalConstant(true)
|
||||||
global.SetUnnamedAddr(true)
|
global.SetUnnamedAddr(true)
|
||||||
global.SetAlignment(1)
|
|
||||||
initializer := llvm.ConstNull(globalLLVMType)
|
initializer := llvm.ConstNull(globalLLVMType)
|
||||||
initializer = b.CreateInsertValue(initializer, funcContext, 0, "")
|
initializer = b.CreateInsertValue(initializer, funcContext, 0, "")
|
||||||
initializer = b.CreateInsertValue(initializer, funcPtr, 1, "")
|
initializer = b.CreateInsertValue(initializer, funcPtr, 1, "")
|
||||||
|
|||||||
+11
-5
@@ -6,11 +6,17 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/src/tinygo"
|
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// constants for hashmap algorithms; must match src/runtime/hashmap.go
|
||||||
|
const (
|
||||||
|
hashmapAlgorithmBinary = iota
|
||||||
|
hashmapAlgorithmString
|
||||||
|
hashmapAlgorithmInterface
|
||||||
|
)
|
||||||
|
|
||||||
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
|
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
|
||||||
// initializing an appropriately sized object.
|
// initializing an appropriately sized object.
|
||||||
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
||||||
@@ -18,20 +24,20 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
|||||||
keyType := mapType.Key().Underlying()
|
keyType := mapType.Key().Underlying()
|
||||||
llvmValueType := b.getLLVMType(mapType.Elem().Underlying())
|
llvmValueType := b.getLLVMType(mapType.Elem().Underlying())
|
||||||
var llvmKeyType llvm.Type
|
var llvmKeyType llvm.Type
|
||||||
var alg uint64
|
var alg uint64 // must match values in src/runtime/hashmap.go
|
||||||
if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
|
if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
|
||||||
// String keys.
|
// String keys.
|
||||||
llvmKeyType = b.getLLVMType(keyType)
|
llvmKeyType = b.getLLVMType(keyType)
|
||||||
alg = uint64(tinygo.HashmapAlgorithmString)
|
alg = hashmapAlgorithmString
|
||||||
} else if hashmapIsBinaryKey(keyType) {
|
} else if hashmapIsBinaryKey(keyType) {
|
||||||
// Trivially comparable keys.
|
// Trivially comparable keys.
|
||||||
llvmKeyType = b.getLLVMType(keyType)
|
llvmKeyType = b.getLLVMType(keyType)
|
||||||
alg = uint64(tinygo.HashmapAlgorithmBinary)
|
alg = hashmapAlgorithmBinary
|
||||||
} else {
|
} else {
|
||||||
// All other keys. Implemented as map[interface{}]valueType for ease of
|
// All other keys. Implemented as map[interface{}]valueType for ease of
|
||||||
// implementation.
|
// implementation.
|
||||||
llvmKeyType = b.getLLVMRuntimeType("_interface")
|
llvmKeyType = b.getLLVMRuntimeType("_interface")
|
||||||
alg = uint64(tinygo.HashmapAlgorithmInterface)
|
alg = hashmapAlgorithmInterface
|
||||||
}
|
}
|
||||||
keySize := b.targetData.TypeAllocSize(llvmKeyType)
|
keySize := b.targetData.TypeAllocSize(llvmKeyType)
|
||||||
valueSize := b.targetData.TypeAllocSize(llvmValueType)
|
valueSize := b.targetData.TypeAllocSize(llvmValueType)
|
||||||
|
|||||||
+105
-184
@@ -12,7 +12,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
|
||||||
"github.com/tinygo-org/tinygo/loader"
|
"github.com/tinygo-org/tinygo/loader"
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
@@ -24,17 +23,15 @@ import (
|
|||||||
// The linkName value contains a valid link name, even if //go:linkname is not
|
// The linkName value contains a valid link name, even if //go:linkname is not
|
||||||
// present.
|
// present.
|
||||||
type functionInfo struct {
|
type functionInfo struct {
|
||||||
wasmModule string // go:wasm-module
|
wasmModule string // go:wasm-module
|
||||||
wasmName string // wasm-export-name or wasm-import-name in the IR
|
wasmName string // wasm-export-name or wasm-import-name in the IR
|
||||||
wasmExport string // go:wasmexport is defined (export is unset, this adds an exported wrapper)
|
linkName string // go:linkname, go:export - the IR function name
|
||||||
wasmExportPos token.Pos // position of //go:wasmexport comment
|
section string // go:section - object file section name
|
||||||
linkName string // go:linkname, go:export - the IR function name
|
exported bool // go:export, CGo
|
||||||
section string // go:section - object file section name
|
interrupt bool // go:interrupt
|
||||||
exported bool // go:export, CGo
|
nobounds bool // go:nobounds
|
||||||
interrupt bool // go:interrupt
|
variadic bool // go:variadic (CGo only)
|
||||||
nobounds bool // go:nobounds
|
inline inlineType // go:inline
|
||||||
variadic bool // go:variadic (CGo only)
|
|
||||||
inline inlineType // go:inline
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type inlineType int
|
type inlineType int
|
||||||
@@ -173,12 +170,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
|||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
||||||
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
||||||
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
||||||
case "runtime.stringFromBytes":
|
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
|
||||||
case "runtime.stringFromRunes":
|
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
|
||||||
case "runtime.trackPointer":
|
case "runtime.trackPointer":
|
||||||
// This function is necessary for tracking pointers on the stack in a
|
// This function is necessary for tracking pointers on the stack in a
|
||||||
// portable way (see gc_stack_portable.go). Indicate to the optimizer
|
// portable way (see gc_stack_portable.go). Indicate to the optimizer
|
||||||
@@ -250,22 +241,8 @@ func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
|
|||||||
// Pick the default linkName.
|
// Pick the default linkName.
|
||||||
linkName: f.RelString(nil),
|
linkName: f.RelString(nil),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a few runtime functions that are treated specially.
|
|
||||||
if info.linkName == "runtime.wasmEntryReactor" && c.BuildMode == "c-shared" {
|
|
||||||
info.linkName = "_initialize"
|
|
||||||
info.wasmName = "_initialize"
|
|
||||||
info.exported = true
|
|
||||||
}
|
|
||||||
if info.linkName == "runtime.wasmEntryCommand" && c.BuildMode == "default" {
|
|
||||||
info.linkName = "_start"
|
|
||||||
info.wasmName = "_start"
|
|
||||||
info.exported = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for //go: pragmas, which may change the link name (among others).
|
// Check for //go: pragmas, which may change the link name (among others).
|
||||||
c.parsePragmas(&info, f)
|
c.parsePragmas(&info, f)
|
||||||
|
|
||||||
c.functionInfos[f] = info
|
c.functionInfos[f] = info
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
@@ -273,164 +250,126 @@ func (c *compilerContext) getFunctionInfo(f *ssa.Function) functionInfo {
|
|||||||
// parsePragmas is used by getFunctionInfo to parse function pragmas such as
|
// parsePragmas is used by getFunctionInfo to parse function pragmas such as
|
||||||
// //export or //go:noinline.
|
// //export or //go:noinline.
|
||||||
func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
||||||
syntax := f.Syntax()
|
if f.Syntax() == nil {
|
||||||
if f.Origin() != nil {
|
|
||||||
syntax = f.Origin().Syntax()
|
|
||||||
}
|
|
||||||
if syntax == nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if decl, ok := f.Syntax().(*ast.FuncDecl); ok && decl.Doc != nil {
|
||||||
// Read all pragmas of this function.
|
|
||||||
var pragmas []*ast.Comment
|
|
||||||
hasWasmExport := false
|
|
||||||
if decl, ok := syntax.(*ast.FuncDecl); ok && decl.Doc != nil {
|
|
||||||
for _, comment := range decl.Doc.List {
|
for _, comment := range decl.Doc.List {
|
||||||
text := comment.Text
|
text := comment.Text
|
||||||
if strings.HasPrefix(text, "//go:") || strings.HasPrefix(text, "//export ") {
|
if strings.HasPrefix(text, "//export ") {
|
||||||
pragmas = append(pragmas, comment)
|
// Rewrite '//export' to '//go:export' for compatibility with
|
||||||
if strings.HasPrefix(comment.Text, "//go:wasmexport ") {
|
// gc.
|
||||||
hasWasmExport = true
|
text = "//go:" + text[2:]
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(text, "//go:") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parts := strings.Fields(text)
|
||||||
|
switch parts[0] {
|
||||||
|
case "//go:export":
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse each pragma.
|
info.linkName = parts[1]
|
||||||
for _, comment := range pragmas {
|
info.wasmName = info.linkName
|
||||||
parts := strings.Fields(comment.Text)
|
info.exported = true
|
||||||
switch parts[0] {
|
case "//go:interrupt":
|
||||||
case "//export", "//go:export":
|
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||||
if len(parts) != 2 {
|
info.interrupt = true
|
||||||
continue
|
}
|
||||||
}
|
case "//go:wasm-module":
|
||||||
if hasWasmExport {
|
// Alternative comment for setting the import module.
|
||||||
// //go:wasmexport overrides //export.
|
// This is deprecated, use //go:wasmimport instead.
|
||||||
continue
|
if len(parts) != 2 {
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
info.linkName = parts[1]
|
info.wasmModule = parts[1]
|
||||||
info.wasmName = info.linkName
|
case "//go:wasmimport":
|
||||||
info.exported = true
|
// Import a WebAssembly function, for example a WASI function.
|
||||||
case "//go:interrupt":
|
// Original proposal: https://github.com/golang/go/issues/38248
|
||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
// Allow globally: https://github.com/golang/go/issues/59149
|
||||||
info.interrupt = true
|
if len(parts) != 3 {
|
||||||
}
|
continue
|
||||||
case "//go:wasm-module":
|
}
|
||||||
// Alternative comment for setting the import module.
|
c.checkWasmImport(f, comment.Text)
|
||||||
// This is deprecated, use //go:wasmimport instead.
|
info.exported = true
|
||||||
if len(parts) != 2 {
|
info.wasmModule = parts[1]
|
||||||
continue
|
info.wasmName = parts[2]
|
||||||
}
|
case "//go:inline":
|
||||||
info.wasmModule = parts[1]
|
info.inline = inlineHint
|
||||||
case "//go:wasmimport":
|
case "//go:noinline":
|
||||||
// Import a WebAssembly function, for example a WASI function.
|
|
||||||
// Original proposal: https://github.com/golang/go/issues/38248
|
|
||||||
// Allow globally: https://github.com/golang/go/issues/59149
|
|
||||||
if len(parts) != 3 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if f.Blocks != nil {
|
|
||||||
// Defined functions cannot be exported.
|
|
||||||
c.addError(f.Pos(), "can only use //go:wasmimport on declarations")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
c.checkWasmImportExport(f, comment.Text)
|
|
||||||
info.exported = true
|
|
||||||
info.wasmModule = parts[1]
|
|
||||||
info.wasmName = parts[2]
|
|
||||||
case "//go:wasmexport":
|
|
||||||
if f.Blocks == nil {
|
|
||||||
c.addError(f.Pos(), "can only use //go:wasmexport on definitions")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(parts) != 2 {
|
|
||||||
c.addError(f.Pos(), fmt.Sprintf("expected one parameter to //go:wasmimport, not %d", len(parts)-1))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := parts[1]
|
|
||||||
if name == "_start" || name == "_initialize" {
|
|
||||||
c.addError(f.Pos(), fmt.Sprintf("//go:wasmexport does not allow %#v", name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if c.BuildMode != "c-shared" && f.RelString(nil) == "main.main" {
|
|
||||||
c.addError(f.Pos(), fmt.Sprintf("//go:wasmexport does not allow main.main to be exported with -buildmode=%s", c.BuildMode))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if c.archFamily() != "wasm32" {
|
|
||||||
c.addError(f.Pos(), "//go:wasmexport is only supported on wasm")
|
|
||||||
}
|
|
||||||
c.checkWasmImportExport(f, comment.Text)
|
|
||||||
info.wasmExport = name
|
|
||||||
info.wasmExportPos = comment.Slash
|
|
||||||
case "//go:inline":
|
|
||||||
info.inline = inlineHint
|
|
||||||
case "//go:noinline":
|
|
||||||
info.inline = inlineNone
|
|
||||||
case "//go:linkname":
|
|
||||||
if len(parts) != 3 || parts[1] != f.Name() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Only enable go:linkname when the package imports "unsafe".
|
|
||||||
// This is a slightly looser requirement than what gc uses: gc
|
|
||||||
// requires the file to import "unsafe", not the package as a
|
|
||||||
// whole.
|
|
||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
|
||||||
info.linkName = parts[2]
|
|
||||||
}
|
|
||||||
case "//go:section":
|
|
||||||
// Only enable go:section when the package imports "unsafe".
|
|
||||||
// go:section also implies go:noinline since inlining could
|
|
||||||
// move the code to a different section than that requested.
|
|
||||||
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
|
|
||||||
info.section = parts[1]
|
|
||||||
info.inline = inlineNone
|
info.inline = inlineNone
|
||||||
}
|
case "//go:linkname":
|
||||||
case "//go:nobounds":
|
if len(parts) != 3 || parts[1] != f.Name() {
|
||||||
// Skip bounds checking in this function. Useful for some
|
continue
|
||||||
// runtime functions.
|
}
|
||||||
// This is somewhat dangerous and thus only imported in packages
|
// Only enable go:linkname when the package imports "unsafe".
|
||||||
// that import unsafe.
|
// This is a slightly looser requirement than what gc uses: gc
|
||||||
if hasUnsafeImport(f.Pkg.Pkg) {
|
// requires the file to import "unsafe", not the package as a
|
||||||
info.nobounds = true
|
// whole.
|
||||||
}
|
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||||
case "//go:variadic":
|
info.linkName = parts[2]
|
||||||
// The //go:variadic pragma is emitted by the CGo preprocessing
|
}
|
||||||
// pass for C variadic functions. This includes both explicit
|
case "//go:section":
|
||||||
// (with ...) and implicit (no parameters in signature)
|
// Only enable go:section when the package imports "unsafe".
|
||||||
// functions.
|
// go:section also implies go:noinline since inlining could
|
||||||
if strings.HasPrefix(f.Name(), "C.") {
|
// move the code to a different section than that requested.
|
||||||
// This prefix cannot naturally be created, it must have
|
if len(parts) == 2 && hasUnsafeImport(f.Pkg.Pkg) {
|
||||||
// been created as a result of CGo preprocessing.
|
info.section = parts[1]
|
||||||
info.variadic = true
|
info.inline = inlineNone
|
||||||
|
}
|
||||||
|
case "//go:nobounds":
|
||||||
|
// Skip bounds checking in this function. Useful for some
|
||||||
|
// runtime functions.
|
||||||
|
// This is somewhat dangerous and thus only imported in packages
|
||||||
|
// that import unsafe.
|
||||||
|
if hasUnsafeImport(f.Pkg.Pkg) {
|
||||||
|
info.nobounds = true
|
||||||
|
}
|
||||||
|
case "//go:variadic":
|
||||||
|
// The //go:variadic pragma is emitted by the CGo preprocessing
|
||||||
|
// pass for C variadic functions. This includes both explicit
|
||||||
|
// (with ...) and implicit (no parameters in signature)
|
||||||
|
// functions.
|
||||||
|
if strings.HasPrefix(f.Name(), "C.") {
|
||||||
|
// This prefix cannot naturally be created, it must have
|
||||||
|
// been created as a result of CGo preprocessing.
|
||||||
|
info.variadic = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether this function can be used in //go:wasmimport or
|
// Check whether this function cannot be used in //go:wasmimport. It will add an
|
||||||
// //go:wasmexport. It will add an error if this is not the case.
|
// error if this is the case.
|
||||||
//
|
//
|
||||||
// The list of allowed types is based on this proposal:
|
// The list of allowed types is based on this proposal:
|
||||||
// https://github.com/golang/go/issues/59149
|
// https://github.com/golang/go/issues/59149
|
||||||
func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string) {
|
func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
|
||||||
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" {
|
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
|
// The runtime is a special case. Allow all kinds of parameters
|
||||||
// (importantly, including pointers).
|
// (importantly, including pointers).
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if f.Blocks != nil {
|
||||||
|
// Defined functions cannot be exported.
|
||||||
|
c.addError(f.Pos(), "can only use //go:wasmimport on declarations")
|
||||||
|
return
|
||||||
|
}
|
||||||
if f.Signature.Results().Len() > 1 {
|
if f.Signature.Results().Len() > 1 {
|
||||||
c.addError(f.Signature.Results().At(1).Pos(), fmt.Sprintf("%s: too many return values", pragma))
|
c.addError(f.Signature.Results().At(1).Pos(), fmt.Sprintf("%s: too many return values", pragma))
|
||||||
} else if f.Signature.Results().Len() == 1 {
|
} else if f.Signature.Results().Len() == 1 {
|
||||||
result := f.Signature.Results().At(0)
|
result := f.Signature.Results().At(0)
|
||||||
if !c.isValidWasmType(result.Type(), siteResult) {
|
if !isValidWasmType(result.Type(), siteResult) {
|
||||||
c.addError(result.Pos(), fmt.Sprintf("%s: unsupported result type %s", pragma, result.Type().String()))
|
c.addError(result.Pos(), fmt.Sprintf("%s: unsupported result type %s", pragma, result.Type().String()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, param := range f.Params {
|
for _, param := range f.Params {
|
||||||
// Check whether the type is allowed.
|
// Check whether the type is allowed.
|
||||||
// Only a very limited number of types can be mapped to WebAssembly.
|
// Only a very limited number of types can be mapped to WebAssembly.
|
||||||
if !c.isValidWasmType(param.Type(), siteParam) {
|
if !isValidWasmType(param.Type(), siteParam) {
|
||||||
c.addError(param.Pos(), fmt.Sprintf("%s: unsupported parameter type %s", pragma, param.Type().String()))
|
c.addError(param.Pos(), fmt.Sprintf("%s: unsupported parameter type %s", pragma, param.Type().String()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,15 +382,13 @@ func (c *compilerContext) checkWasmImportExport(f *ssa.Function, pragma string)
|
|||||||
//
|
//
|
||||||
// This previously reflected the additional restrictions documented here:
|
// This previously reflected the additional restrictions documented here:
|
||||||
// https://github.com/golang/go/issues/59149
|
// https://github.com/golang/go/issues/59149
|
||||||
func (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {
|
func isValidWasmType(typ types.Type, site wasmSite) bool {
|
||||||
switch typ := typ.Underlying().(type) {
|
switch typ := typ.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case types.Bool:
|
case types.Bool:
|
||||||
return true
|
return true
|
||||||
case types.Int8, types.Uint8, types.Int16, types.Uint16:
|
case types.Int, types.Uint, types.Int8, types.Uint8, types.Int16, types.Uint16, types.Int32, types.Uint32, types.Int64, types.Uint64:
|
||||||
return site == siteIndirect
|
|
||||||
case types.Int32, types.Uint32, types.Int64, types.Uint64:
|
|
||||||
return true
|
return true
|
||||||
case types.Float32, types.Float64:
|
case types.Float32, types.Float64:
|
||||||
return true
|
return true
|
||||||
@@ -462,35 +399,19 @@ func (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {
|
|||||||
return site == siteParam || site == siteIndirect
|
return site == siteParam || site == siteIndirect
|
||||||
}
|
}
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return site == siteIndirect && c.isValidWasmType(typ.Elem(), siteIndirect)
|
return site == siteIndirect && isValidWasmType(typ.Elem(), siteIndirect)
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
if site != siteIndirect {
|
if site != siteIndirect {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Structs with no fields do not need structs.HostLayout
|
|
||||||
if typ.NumFields() == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
hasHostLayout := true // default to true before detecting Go version
|
|
||||||
// (*types.Package).GoVersion added in go1.21
|
|
||||||
if gv, ok := any(c.pkg).(interface{ GoVersion() string }); ok {
|
|
||||||
if goenv.Compare(gv.GoVersion(), "go1.23") >= 0 {
|
|
||||||
hasHostLayout = false // package structs added in go1.23
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < typ.NumFields(); i++ {
|
for i := 0; i < typ.NumFields(); i++ {
|
||||||
ftyp := typ.Field(i).Type()
|
if !isValidWasmType(typ.Field(i).Type(), siteIndirect) {
|
||||||
if ftyp.String() == "structs.HostLayout" {
|
|
||||||
hasHostLayout = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !c.isValidWasmType(ftyp, siteIndirect) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasHostLayout
|
return true
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
return c.isValidWasmType(typ.Elem(), siteIndirect)
|
return isValidWasmType(typ.Elem(), siteIndirect)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+7
-37
@@ -1,9 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "unsafe"
|
||||||
"structs"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:wasmimport modulename empty
|
//go:wasmimport modulename empty
|
||||||
func empty()
|
func empty()
|
||||||
@@ -17,37 +14,31 @@ func implementation() {
|
|||||||
type Uint uint32
|
type Uint uint32
|
||||||
|
|
||||||
type S struct {
|
type S struct {
|
||||||
_ structs.HostLayout
|
|
||||||
a [4]uint32
|
a [4]uint32
|
||||||
b uintptr
|
b uintptr
|
||||||
|
c int
|
||||||
d float32
|
d float32
|
||||||
e float64
|
e float64
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:wasmimport modulename validparam
|
//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, j *struct{}, k *[8]uint8)
|
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 [4]uint32
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte
|
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type struct{a int}
|
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type struct{a int}
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type chan struct{}
|
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type chan struct{}
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type func()
|
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type func()
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int
|
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type uint
|
|
||||||
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type [8]int
|
|
||||||
//
|
//
|
||||||
//go:wasmimport modulename invalidparam
|
//go:wasmimport modulename invalidparam
|
||||||
func invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func(), f int, g uint, h [8]int)
|
func invalidparam(a [4]uint32, b []byte, c struct{ a int }, d chan struct{}, e func())
|
||||||
|
|
||||||
// ERROR: //go:wasmimport modulename invalidparam_no_hostlayout: unsupported parameter type *struct{int}
|
|
||||||
// ERROR: //go:wasmimport modulename invalidparam_no_hostlayout: unsupported parameter type *struct{string}
|
|
||||||
//
|
|
||||||
//go:wasmimport modulename invalidparam_no_hostlayout
|
|
||||||
func invalidparam_no_hostlayout(a *struct{ int }, b *struct{ string })
|
|
||||||
|
|
||||||
//go:wasmimport modulename validreturn_int32
|
//go:wasmimport modulename validreturn_int32
|
||||||
func validreturn_int32() int32
|
func validreturn_int32() int32
|
||||||
|
|
||||||
|
//go:wasmimport modulename validreturn_int
|
||||||
|
func validreturn_int() int
|
||||||
|
|
||||||
//go:wasmimport modulename validreturn_ptr_int32
|
//go:wasmimport modulename validreturn_ptr_int32
|
||||||
func validreturn_ptr_int32() *int32
|
func validreturn_ptr_int32() *int32
|
||||||
|
|
||||||
@@ -57,12 +48,6 @@ func validreturn_ptr_string() *string
|
|||||||
//go:wasmimport modulename validreturn_ptr_struct
|
//go:wasmimport modulename validreturn_ptr_struct
|
||||||
func validreturn_ptr_struct() *S
|
func validreturn_ptr_struct() *S
|
||||||
|
|
||||||
//go:wasmimport modulename validreturn_ptr_struct
|
|
||||||
func validreturn_ptr_empty_struct() *struct{}
|
|
||||||
|
|
||||||
//go:wasmimport modulename validreturn_ptr_array
|
|
||||||
func validreturn_ptr_array() *[8]uint8
|
|
||||||
|
|
||||||
//go:wasmimport modulename validreturn_unsafe_pointer
|
//go:wasmimport modulename validreturn_unsafe_pointer
|
||||||
func validreturn_unsafe_pointer() unsafe.Pointer
|
func validreturn_unsafe_pointer() unsafe.Pointer
|
||||||
|
|
||||||
@@ -71,26 +56,11 @@ func validreturn_unsafe_pointer() unsafe.Pointer
|
|||||||
//go:wasmimport modulename manyreturns
|
//go:wasmimport modulename manyreturns
|
||||||
func manyreturns() (int32, int32)
|
func manyreturns() (int32, int32)
|
||||||
|
|
||||||
// ERROR: //go:wasmimport modulename invalidreturn_int: unsupported result type int
|
|
||||||
//
|
|
||||||
//go:wasmimport modulename invalidreturn_int
|
|
||||||
func invalidreturn_int() int
|
|
||||||
|
|
||||||
// ERROR: //go:wasmimport modulename invalidreturn_int: unsupported result type uint
|
|
||||||
//
|
|
||||||
//go:wasmimport modulename invalidreturn_int
|
|
||||||
func invalidreturn_uint() uint
|
|
||||||
|
|
||||||
// ERROR: //go:wasmimport modulename invalidreturn_func: unsupported result type func()
|
// ERROR: //go:wasmimport modulename invalidreturn_func: unsupported result type func()
|
||||||
//
|
//
|
||||||
//go:wasmimport modulename invalidreturn_func
|
//go:wasmimport modulename invalidreturn_func
|
||||||
func invalidreturn_func() func()
|
func invalidreturn_func() func()
|
||||||
|
|
||||||
// ERROR: //go:wasmimport modulename invalidreturn_pointer_array_int: unsupported result type *[8]int
|
|
||||||
//
|
|
||||||
//go:wasmimport modulename invalidreturn_pointer_array_int
|
|
||||||
func invalidreturn_pointer_array_int() *[8]int
|
|
||||||
|
|
||||||
// ERROR: //go:wasmimport modulename invalidreturn_slice_byte: unsupported result type []byte
|
// ERROR: //go:wasmimport modulename invalidreturn_slice_byte: unsupported result type []byte
|
||||||
//
|
//
|
||||||
//go:wasmimport modulename invalidreturn_slice_byte
|
//go:wasmimport modulename invalidreturn_slice_byte
|
||||||
|
|||||||
Vendored
-16
@@ -48,22 +48,6 @@ func inlineFunc() {
|
|||||||
func noinlineFunc() {
|
func noinlineFunc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Int interface {
|
|
||||||
int8 | int16
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same for generic functions (but the compiler may miss the pragma due to it
|
|
||||||
// being generic).
|
|
||||||
//
|
|
||||||
//go:noinline
|
|
||||||
func noinlineGenericFunc[T Int]() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func useGeneric() {
|
|
||||||
// Make sure the generic function above is instantiated.
|
|
||||||
noinlineGenericFunc[int8]()
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function should have the specified section.
|
// This function should have the specified section.
|
||||||
//
|
//
|
||||||
//go:section .special_function_section
|
//go:section .special_function_section
|
||||||
|
|||||||
Vendored
-13
@@ -48,19 +48,6 @@ entry:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden void @main.useGeneric(ptr %context) unnamed_addr #2 {
|
|
||||||
entry:
|
|
||||||
call void @"main.noinlineGenericFunc[int8]"(ptr undef)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
|
||||||
define linkonce_odr hidden void @"main.noinlineGenericFunc[int8]"(ptr %context) unnamed_addr #5 {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: noinline nounwind
|
; Function Attrs: noinline nounwind
|
||||||
define hidden void @main.functionInSection(ptr %context) unnamed_addr #5 section ".special_function_section" {
|
define hidden void @main.functionInSection(ptr %context) unnamed_addr #5 section ".special_function_section" {
|
||||||
entry:
|
entry:
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ func TestErrors(t *testing.T) {
|
|||||||
{name: "cgo"},
|
{name: "cgo"},
|
||||||
{name: "compiler"},
|
{name: "compiler"},
|
||||||
{name: "interp"},
|
{name: "interp"},
|
||||||
{name: "invalidmain"},
|
|
||||||
{name: "invalidname"},
|
|
||||||
{name: "linker-flashoverflow", target: "cortex-m-qemu"},
|
{name: "linker-flashoverflow", target: "cortex-m-qemu"},
|
||||||
{name: "linker-ramoverflow", target: "cortex-m-qemu"},
|
{name: "linker-ramoverflow", target: "cortex-m-qemu"},
|
||||||
{name: "linker-undefined", target: "darwin/arm64"},
|
{name: "linker-undefined", target: "darwin/arm64"},
|
||||||
|
|||||||
Generated
+4
-4
@@ -20,16 +20,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1728500571,
|
"lastModified": 1703068421,
|
||||||
"narHash": "sha256-dOymOQ3AfNI4Z337yEwHGohrVQb4yPODCW9MDUyAc4w=",
|
"narHash": "sha256-WSw5Faqlw75McIflnl5v7qVD/B3S2sLh+968bpOGrWA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "d51c28603def282a24fa034bcb007e2bcb5b5dd0",
|
"rev": "d65bceaee0fb1e64363f7871bc43dc1c6ecad99f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-24.05",
|
"ref": "nixos-23.11",
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
# Use a recent stable release, but fix the version to make it reproducible.
|
# Use a recent stable release, but fix the version to make it reproducible.
|
||||||
# This version should be updated from time to time.
|
# This version should be updated from time to time.
|
||||||
nixpkgs.url = "nixpkgs/nixos-24.05";
|
nixpkgs.url = "nixpkgs/nixos-23.11";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
outputs = { self, nixpkgs, flake-utils }:
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
@@ -49,11 +49,11 @@
|
|||||||
buildInputs = [
|
buildInputs = [
|
||||||
# These dependencies are required for building tinygo (go install).
|
# These dependencies are required for building tinygo (go install).
|
||||||
go
|
go
|
||||||
llvmPackages_18.llvm
|
llvmPackages_17.llvm
|
||||||
llvmPackages_18.libclang
|
llvmPackages_17.libclang
|
||||||
# Additional dependencies needed at runtime, for building and/or
|
# Additional dependencies needed at runtime, for building and/or
|
||||||
# flashing.
|
# flashing.
|
||||||
llvmPackages_18.lld
|
llvmPackages_17.lld
|
||||||
avrdude
|
avrdude
|
||||||
binaryen
|
binaryen
|
||||||
# Additional dependencies needed for on-chip debugging.
|
# Additional dependencies needed for on-chip debugging.
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
# Without setting these explicitly, Homebrew versions might be used
|
# Without setting these explicitly, Homebrew versions might be used
|
||||||
# or the default `ar` and `nm` tools might be used (which don't
|
# or the default `ar` and `nm` tools might be used (which don't
|
||||||
# support wasi).
|
# support wasi).
|
||||||
export CLANG="clang-18 -resource-dir ${llvmPackages_18.clang.cc.lib}/lib/clang/18"
|
export CLANG="clang-17 -resource-dir ${llvmPackages_17.clang.cc.lib}/lib/clang/17"
|
||||||
export LLVM_AR=llvm-ar
|
export LLVM_AR=llvm-ar
|
||||||
export LLVM_NM=llvm-nm
|
export LLVM_NM=llvm-nm
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
export MD5SUM=md5sum
|
export MD5SUM=md5sum
|
||||||
|
|
||||||
# Ugly hack to make the Clang resources directory available.
|
# Ugly hack to make the Clang resources directory available.
|
||||||
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_18.clang.cc.lib}/lib/clang/18\" -tags=llvm18"
|
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_17.clang.cc.lib}/lib/clang/17\" -tags=llvm17"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ require (
|
|||||||
github.com/mattn/go-colorable v0.1.13
|
github.com/mattn/go-colorable v0.1.13
|
||||||
github.com/mattn/go-tty v0.0.4
|
github.com/mattn/go-tty v0.0.4
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
||||||
github.com/tetratelabs/wazero v1.6.0
|
|
||||||
go.bug.st/serial v1.6.0
|
go.bug.st/serial v1.6.0
|
||||||
golang.org/x/net v0.26.0
|
golang.org/x/net v0.26.0
|
||||||
golang.org/x/sys v0.21.0
|
golang.org/x/sys v0.21.0
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
|
|||||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
@@ -44,18 +45,19 @@ github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3px
|
|||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 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 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g=
|
|
||||||
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
|
||||||
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
||||||
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
||||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||||
|
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-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-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-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -74,5 +76,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 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 h1:bLsZXRUBavt++CJlMN7sppNziqu3LyamESLhFJcpqFQ=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
tinygo.org/x/go-llvm v0.0.0-20240627184919-3b50c76783a8/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
+17
-65
@@ -4,37 +4,29 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"runtime/debug"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const version = "0.35.0-dev"
|
const version = "0.34.0-dev"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// This variable is set at build time using -ldflags parameters.
|
||||||
|
// See: https://stackoverflow.com/a/11355611
|
||||||
|
GitSha1 string
|
||||||
|
)
|
||||||
|
|
||||||
// Return TinyGo version, either in the form 0.30.0 or as a development version
|
// Return TinyGo version, either in the form 0.30.0 or as a development version
|
||||||
// (like 0.30.0-dev-abcd012).
|
// (like 0.30.0-dev-abcd012).
|
||||||
func Version() string {
|
func Version() string {
|
||||||
v := version
|
v := version
|
||||||
if strings.HasSuffix(version, "-dev") {
|
if strings.HasSuffix(version, "-dev") && GitSha1 != "" {
|
||||||
if hash := readGitHash(); hash != "" {
|
v += "-" + GitSha1
|
||||||
v += "-" + hash
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func readGitHash() string {
|
|
||||||
if info, ok := debug.ReadBuildInfo(); ok {
|
|
||||||
for _, setting := range info.Settings {
|
|
||||||
if setting.Key == "vcs.revision" {
|
|
||||||
return setting.Value[:8]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||||
// If the goroot cannot be determined, (0, 0) is returned.
|
// If the goroot cannot be determined, (0, 0) is returned.
|
||||||
func GetGorootVersion() (major, minor int, err error) {
|
func GetGorootVersion() (major, minor int, err error) {
|
||||||
@@ -42,67 +34,27 @@ func GetGorootVersion() (major, minor int, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
major, minor, _, err = Parse(s)
|
|
||||||
return major, minor, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses the Go version (like "go1.3.2") in the parameter and return the
|
if s == "" || s[:2] != "go" {
|
||||||
// major, minor, and patch version: 1, 3, and 2 in this example.
|
return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
|
||||||
// If there is an error, (0, 0, 0) and an error will be returned.
|
|
||||||
func Parse(version string) (major, minor, patch int, err error) {
|
|
||||||
if strings.HasPrefix(version, "devel ") {
|
|
||||||
version = strings.Split(strings.TrimPrefix(version, "devel "), version)[0]
|
|
||||||
}
|
|
||||||
if version == "" || version[:2] != "go" {
|
|
||||||
return 0, 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(version[2:], ".")
|
parts := strings.Split(s[2:], ".")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
return 0, 0, 0, errors.New("could not parse Go version: version has less than two parts")
|
return 0, 0, errors.New("could not parse Go version: version has less than two parts")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore the errors, we don't really handle errors here anyway.
|
// Ignore the errors, we don't really handle errors here anyway.
|
||||||
var trailing string
|
var trailing string
|
||||||
n, err := fmt.Sscanf(version, "go%d.%d.%d%s", &major, &minor, &patch, &trailing)
|
n, err := fmt.Sscanf(s, "go%d.%d%s", &major, &minor, &trailing)
|
||||||
if n == 2 {
|
if n == 2 && err == io.EOF {
|
||||||
n, err = fmt.Sscanf(version, "go%d.%d%s", &major, &minor, &trailing)
|
|
||||||
}
|
|
||||||
if n >= 2 && err == io.EOF {
|
|
||||||
// Means there were no trailing characters (i.e., not an alpha/beta)
|
// Means there were no trailing characters (i.e., not an alpha/beta)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, fmt.Errorf("failed to parse version: %s", err)
|
return 0, 0, fmt.Errorf("failed to parse version: %s", err)
|
||||||
}
|
|
||||||
|
|
||||||
return major, minor, patch, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare compares two Go version strings.
|
|
||||||
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
|
|
||||||
// If either a or b is not a valid Go version, it is treated as "go0.0"
|
|
||||||
// and compared lexicographically.
|
|
||||||
// See [Parse] for more information.
|
|
||||||
func Compare(a, b string) int {
|
|
||||||
aMajor, aMinor, aPatch, _ := Parse(a)
|
|
||||||
bMajor, bMinor, bPatch, _ := Parse(b)
|
|
||||||
switch {
|
|
||||||
case aMajor < bMajor:
|
|
||||||
return -1
|
|
||||||
case aMajor > bMajor:
|
|
||||||
return +1
|
|
||||||
case aMinor < bMinor:
|
|
||||||
return -1
|
|
||||||
case aMinor > bMinor:
|
|
||||||
return +1
|
|
||||||
case aPatch < bPatch:
|
|
||||||
return -1
|
|
||||||
case aPatch > bPatch:
|
|
||||||
return +1
|
|
||||||
default:
|
|
||||||
return strings.Compare(a, b)
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GorootVersionString returns the version string as reported by the Go
|
// GorootVersionString returns the version string as reported by the Go
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
package goenv
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestParse(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
v string
|
|
||||||
major int
|
|
||||||
minor int
|
|
||||||
patch int
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{"", 0, 0, 0, true},
|
|
||||||
{"go", 0, 0, 0, true},
|
|
||||||
{"go1", 0, 0, 0, true},
|
|
||||||
{"go.0", 0, 0, 0, true},
|
|
||||||
{"go1.0", 1, 0, 0, false},
|
|
||||||
{"go1.1", 1, 1, 0, false},
|
|
||||||
{"go1.23", 1, 23, 0, false},
|
|
||||||
{"go1.23.5", 1, 23, 5, false},
|
|
||||||
{"go1.23.5-rc6", 1, 23, 5, false},
|
|
||||||
{"go2.0", 2, 0, 0, false},
|
|
||||||
{"go2.0.15", 2, 0, 15, false},
|
|
||||||
{"devel go1.24-f99f5da18f Thu Nov 14 22:29:26 2024 +0000 darwin/arm64", 1, 24, 0, false},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.v, func(t *testing.T) {
|
|
||||||
major, minor, patch, err := Parse(tt.v)
|
|
||||||
if err == nil && tt.wantErr {
|
|
||||||
t.Errorf("Parse(%q): expected err != nil", tt.v)
|
|
||||||
}
|
|
||||||
if err != nil && !tt.wantErr {
|
|
||||||
t.Errorf("Parse(%q): expected err == nil", tt.v)
|
|
||||||
}
|
|
||||||
if major != tt.major || minor != tt.minor || patch != tt.patch {
|
|
||||||
t.Errorf("Parse(%q): expected %d, %d, %d, nil; got %d, %d, %d, %v",
|
|
||||||
tt.v, tt.major, tt.minor, tt.patch, major, minor, patch, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompare(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
a string
|
|
||||||
b string
|
|
||||||
want int
|
|
||||||
}{
|
|
||||||
{"", "", 0},
|
|
||||||
{"go0", "go0", 0},
|
|
||||||
{"go0", "go1", -1},
|
|
||||||
{"go1", "go0", 1},
|
|
||||||
{"go1", "go2", -1},
|
|
||||||
{"go2", "go1", 1},
|
|
||||||
{"go1.1", "go1.2", -1},
|
|
||||||
{"go1.2", "go1.1", 1},
|
|
||||||
{"go1.1.0", "go1.2.0", -1},
|
|
||||||
{"go1.2.0", "go1.1.0", 1},
|
|
||||||
{"go1.2.0", "go2.3.0", -1},
|
|
||||||
{"go1.23.2", "go1.23.10", -1},
|
|
||||||
{"go0.1.22", "go1.23.101", -1},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.a+" "+tt.b, func(t *testing.T) {
|
|
||||||
got := Compare(tt.a, tt.b)
|
|
||||||
if got != tt.want {
|
|
||||||
t.Errorf("Compare(%q, %q): expected %d; got %d",
|
|
||||||
tt.a, tt.b, tt.want, got)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,17 +2,11 @@ module github.com/tinygo-org/tinygo/internal/tools
|
|||||||
|
|
||||||
go 1.22.4
|
go 1.22.4
|
||||||
|
|
||||||
require github.com/bytecodealliance/wasm-tools-go v0.3.1
|
require github.com/bytecodealliance/wasm-tools-go v0.2.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/coreos/go-semver v0.3.1 // indirect
|
github.com/coreos/go-semver v0.3.1 // indirect
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
github.com/urfave/cli/v3 v3.0.0-alpha9 // indirect
|
||||||
github.com/klauspost/compress v1.17.9 // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
|
||||||
github.com/regclient/regclient v0.7.1 // indirect
|
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
|
||||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-alpha9.2 // indirect
|
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
+10
-29
@@ -1,44 +1,25 @@
|
|||||||
github.com/bytecodealliance/wasm-tools-go v0.3.1 h1:9Q9PjSzkbiVmkUvZ7nYCfJ02mcQDBalxycA3s8g7kR4=
|
github.com/bytecodealliance/wasm-tools-go v0.2.0 h1:JdmiZew7ewHjf+ZGGRE4gZM85Ad/PGW/5I57hepEOjQ=
|
||||||
github.com/bytecodealliance/wasm-tools-go v0.3.1/go.mod h1:vNAQ8DAEp6xvvk+TUHah5DslLEa76f4H6e737OeaxuY=
|
github.com/bytecodealliance/wasm-tools-go v0.2.0/go.mod h1:2GnJCUlcDrslZ/L6+yYqoUnewDlBvqRS2N/0NW9ro6w=
|
||||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
|
||||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
|
||||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
|
||||||
github.com/olareg/olareg v0.1.0 h1:1dXBOgPrig5N7zoXyIZVQqU0QBo6sD9pbL6UYjY75CA=
|
|
||||||
github.com/olareg/olareg v0.1.0/go.mod h1:RBuU7JW7SoIIxZKzLRhq8sVtQeAHzCAtRrXEBx2KlM4=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/regclient/regclient v0.7.1 h1:qEsJrTmZd98fZKjueAbrZCSNGU+ifnr6xjlSAs3WOPs=
|
|
||||||
github.com/regclient/regclient v0.7.1/go.mod h1:+w/BFtJuw0h0nzIw/z2+1FuA2/dVXBzDq4rYmziJpMc=
|
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/urfave/cli/v3 v3.0.0-alpha9 h1:P0RMy5fQm1AslQS+XCmy9UknDXctOmG/q/FZkUFnJSo=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/urfave/cli/v3 v3.0.0-alpha9/go.mod h1:0kK/RUFHyh+yIKSfWxwheGndfnrvYSmYFVeKCh03ZUc=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
|
||||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-alpha9.2 h1:CL8llQj3dGRLVQQzHxS+ZYRLanOuhyK1fXgLKD+qV+Y=
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-alpha9.2/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
|
||||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
+24
-29
@@ -229,35 +229,30 @@ func needsSyscallPackage(buildTags []string) bool {
|
|||||||
// means use the TinyGo version.
|
// means use the TinyGo version.
|
||||||
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
||||||
paths := map[string]bool{
|
paths := map[string]bool{
|
||||||
"": true,
|
"": true,
|
||||||
"crypto/": true,
|
"crypto/": true,
|
||||||
"crypto/rand/": false,
|
"crypto/rand/": false,
|
||||||
"crypto/tls/": false,
|
"crypto/tls/": false,
|
||||||
"crypto/x509/": true,
|
"device/": false,
|
||||||
"crypto/x509/internal/": true,
|
"examples/": false,
|
||||||
"crypto/x509/internal/macos/": false,
|
"internal/": true,
|
||||||
"device/": false,
|
"internal/abi/": false,
|
||||||
"examples/": false,
|
"internal/binary/": false,
|
||||||
"internal/": true,
|
"internal/bytealg/": false,
|
||||||
"internal/abi/": false,
|
"internal/cm/": false,
|
||||||
"internal/binary/": false,
|
"internal/fuzz/": false,
|
||||||
"internal/bytealg/": false,
|
"internal/reflectlite/": false,
|
||||||
"internal/cm/": false,
|
"internal/task/": false,
|
||||||
"internal/fuzz/": false,
|
"internal/wasi/": false,
|
||||||
"internal/reflectlite/": false,
|
"machine/": false,
|
||||||
"internal/gclayout": false,
|
"net/": true,
|
||||||
"internal/task/": false,
|
"net/http/": false,
|
||||||
"internal/wasi/": false,
|
"os/": true,
|
||||||
"machine/": false,
|
"reflect/": false,
|
||||||
"net/": true,
|
"runtime/": false,
|
||||||
"net/http/": false,
|
"sync/": true,
|
||||||
"os/": true,
|
"testing/": true,
|
||||||
"reflect/": false,
|
"unique/": false,
|
||||||
"runtime/": false,
|
|
||||||
"sync/": true,
|
|
||||||
"testing/": true,
|
|
||||||
"tinygo/": false,
|
|
||||||
"unique/": false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if goMinor >= 19 {
|
if goMinor >= 19 {
|
||||||
|
|||||||
+3
-15
@@ -418,12 +418,8 @@ func (p *Package) Check() error {
|
|||||||
packageName := p.ImportPath
|
packageName := p.ImportPath
|
||||||
if p == p.program.MainPkg() {
|
if p == p.program.MainPkg() {
|
||||||
if p.Name != "main" {
|
if p.Name != "main" {
|
||||||
return Errors{p, []error{
|
// Sanity check. Should not ever trigger.
|
||||||
scanner.Error{
|
panic("expected main package to have name 'main'")
|
||||||
Pos: p.program.fset.Position(p.Files[0].Name.Pos()),
|
|
||||||
Msg: fmt.Sprintf("expected main package to have name \"main\", not %#v", p.Name),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
packageName = "main"
|
packageName = "main"
|
||||||
}
|
}
|
||||||
@@ -432,15 +428,7 @@ func (p *Package) Check() error {
|
|||||||
if err, ok := err.(Errors); ok {
|
if err, ok := err.(Errors); ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(typeErrors) != 0 {
|
return Errors{p, typeErrors}
|
||||||
// Got type errors, so return them.
|
|
||||||
return Errors{p, typeErrors}
|
|
||||||
}
|
|
||||||
// This can happen in some weird cases.
|
|
||||||
// The only case I know is when compiling a Go 1.23 program, with a
|
|
||||||
// TinyGo version that supports Go 1.23 but is compiled using Go 1.22.
|
|
||||||
// So this should be pretty rare.
|
|
||||||
return Errors{p, []error{err}}
|
|
||||||
}
|
}
|
||||||
p.Pkg = typesPkg
|
p.Pkg = typesPkg
|
||||||
|
|
||||||
|
|||||||
@@ -283,6 +283,46 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
// Tests are always run in the package directory.
|
// Tests are always run in the package directory.
|
||||||
cmd.Dir = result.MainDir
|
cmd.Dir = result.MainDir
|
||||||
|
|
||||||
|
// wasmtime is the default emulator used for `-target=wasip1`. wasmtime
|
||||||
|
// is a WebAssembly runtime CLI with WASI enabled by default. However,
|
||||||
|
// only stdio are allowed by default. For example, while STDOUT routes
|
||||||
|
// to the host, other files don't. It also does not inherit environment
|
||||||
|
// variables from the host. Some tests read testdata files, often from
|
||||||
|
// outside the package directory. Other tests require temporary
|
||||||
|
// writeable directories. We allow this by adding wasmtime flags below.
|
||||||
|
if config.EmulatorName() == "wasmtime" {
|
||||||
|
// At this point, The current working directory is at the package
|
||||||
|
// directory. Ex. $GOROOT/src/compress/flate for compress/flate.
|
||||||
|
// buildAndRun has already added arguments for wasmtime, that allow
|
||||||
|
// read-access to files such as "testdata/huffman-zero.in".
|
||||||
|
//
|
||||||
|
// Ex. main(.wasm) --dir=. -- -test.v
|
||||||
|
|
||||||
|
// Below adds additional wasmtime flags in case a test reads files
|
||||||
|
// outside its directory, like "../testdata/e.txt". This allows any
|
||||||
|
// relative directory up to the module root, even if the test never
|
||||||
|
// reads any files.
|
||||||
|
//
|
||||||
|
// Ex. run --dir=.. --dir=../.. --dir=../../..
|
||||||
|
var dirs []string
|
||||||
|
switch config.Target.GOOS {
|
||||||
|
case "wasip1":
|
||||||
|
dirs = dirsToModuleRootRel(result.MainDir, result.ModuleRoot)
|
||||||
|
default:
|
||||||
|
dirs = dirsToModuleRootAbs(result.MainDir, result.ModuleRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"run"}
|
||||||
|
for _, d := range dirs {
|
||||||
|
args = append(args, "--dir="+d)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, "--env=PWD="+cmd.Dir)
|
||||||
|
|
||||||
|
args = append(args, cmd.Args[1:]...)
|
||||||
|
cmd.Args = args
|
||||||
|
}
|
||||||
|
|
||||||
// Run the test.
|
// Run the test.
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
@@ -769,6 +809,9 @@ func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
|
|||||||
// passes command line arguments and environment variables in a way appropriate
|
// passes command line arguments and environment variables in a way appropriate
|
||||||
// for the given emulator.
|
// 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) {
|
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
|
// Determine whether we're on a system that supports environment variables
|
||||||
// and command line parameters (operating systems, WASI) or not (baremetal,
|
// and command line parameters (operating systems, WASI) or not (baremetal,
|
||||||
// WebAssembly in the browser). If we're on a system without an environment,
|
// WebAssembly in the browser). If we're on a system without an environment,
|
||||||
@@ -781,7 +824,7 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
needsEnvInVars = true
|
needsEnvInVars = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var args, env []string
|
var args, emuArgs, env []string
|
||||||
var extraCmdEnv []string
|
var extraCmdEnv []string
|
||||||
if needsEnvInVars {
|
if needsEnvInVars {
|
||||||
runtimeGlobals := make(map[string]string)
|
runtimeGlobals := make(map[string]string)
|
||||||
@@ -801,6 +844,21 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
"runtime": runtimeGlobals,
|
"runtime": runtimeGlobals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if config.EmulatorName() == "wasmtime" {
|
||||||
|
for _, v := range environmentVars {
|
||||||
|
emuArgs = append(emuArgs, "--env", v)
|
||||||
|
}
|
||||||
|
if len(cmdArgs) != 0 {
|
||||||
|
// Use of '--' argument no longer necessary as of Wasmtime v14:
|
||||||
|
// https://github.com/bytecodealliance/wasmtime/pull/6946
|
||||||
|
// args = append(args, "--")
|
||||||
|
args = append(args, cmdArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this for nicer backtraces during tests, but don't override the user.
|
||||||
|
if _, ok := os.LookupEnv("WASMTIME_BACKTRACE_DETAILS"); !ok {
|
||||||
|
extraCmdEnv = append(extraCmdEnv, "WASMTIME_BACKTRACE_DETAILS=1")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Pass environment variables and command line parameters as usual.
|
// Pass environment variables and command line parameters as usual.
|
||||||
// This also works on qemu-aarch64 etc.
|
// This also works on qemu-aarch64 etc.
|
||||||
@@ -843,61 +901,27 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
name, emulator = emulator[0], emulator[1:]
|
name = emulator[0]
|
||||||
|
|
||||||
// wasmtime is a WebAssembly runtime CLI with WASI enabled by default.
|
|
||||||
// By default, only stdio is allowed. For example, while STDOUT routes
|
|
||||||
// to the host, other files don't. It also does not inherit environment
|
|
||||||
// variables from the host. Some tests read testdata files, often from
|
|
||||||
// outside the package directory. Other tests require temporary
|
|
||||||
// writeable directories. We allow this by adding wasmtime flags below.
|
|
||||||
if name == "wasmtime" {
|
if name == "wasmtime" {
|
||||||
var emuArgs []string
|
// Wasmtime needs some special flags to pass environment variables
|
||||||
|
// and allow reading from the current directory.
|
||||||
// Extract the wasmtime subcommand (e.g. "run" or "serve")
|
switch config.Options.Target {
|
||||||
if len(emulator) > 1 {
|
case "wasip1":
|
||||||
emuArgs = append(emuArgs, emulator[0])
|
|
||||||
emulator = emulator[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
wd, _ := os.Getwd()
|
|
||||||
|
|
||||||
// Below adds additional wasmtime flags in case a test reads files
|
|
||||||
// outside its directory, like "../testdata/e.txt". This allows any
|
|
||||||
// relative directory up to the module root, even if the test never
|
|
||||||
// reads any files.
|
|
||||||
if config.TestConfig.CompileTestBinary {
|
|
||||||
// Set working directory to package dir
|
|
||||||
wd = result.MainDir
|
|
||||||
|
|
||||||
// Add relative dirs (../, ../..) up to module root (for wasip1)
|
|
||||||
dirs := dirsToModuleRootRel(result.MainDir, result.ModuleRoot)
|
|
||||||
|
|
||||||
// Add absolute dirs up to module root (for wasip2)
|
|
||||||
dirs = append(dirs, dirsToModuleRootAbs(result.MainDir, result.ModuleRoot)...)
|
|
||||||
|
|
||||||
for _, d := range dirs {
|
|
||||||
emuArgs = append(emuArgs, "--dir="+d)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emuArgs = append(emuArgs, "--dir=.")
|
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, "--dir="+wd)
|
|
||||||
emuArgs = append(emuArgs, "--env=PWD="+wd)
|
|
||||||
for _, v := range environmentVars {
|
|
||||||
emuArgs = append(emuArgs, "--env", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set this for nicer backtraces during tests, but don't override the user.
|
|
||||||
if _, ok := os.LookupEnv("WASMTIME_BACKTRACE_DETAILS"); !ok {
|
|
||||||
extraCmdEnv = append(extraCmdEnv, "WASMTIME_BACKTRACE_DETAILS=1")
|
|
||||||
}
|
|
||||||
|
|
||||||
emulator = append(emuArgs, emulator...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args = append(emulator, args...)
|
emuArgs = append(emuArgs, emulator[1:]...)
|
||||||
|
args = append(emuArgs, args...)
|
||||||
}
|
}
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
if ctx != nil {
|
if ctx != nil {
|
||||||
@@ -927,7 +951,7 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
|
|
||||||
// Run binary.
|
// Run binary.
|
||||||
if config.Options.PrintCommands != nil {
|
if config.Options.PrintCommands != nil {
|
||||||
config.Options.PrintCommands(cmd.Path, cmd.Args[1:]...)
|
config.Options.PrintCommands(cmd.Path, cmd.Args...)
|
||||||
}
|
}
|
||||||
err = run(cmd, result)
|
err = run(cmd, result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1232,169 +1256,36 @@ func getBMPPorts() (gdbPort, uartPort string, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
usageBuild = `Build compiles the packages named by the import paths, along with their
|
|
||||||
dependencies, but it does not install the results. The output binary is
|
|
||||||
specified using the -o parameter. The generated file type depends on the
|
|
||||||
extension:
|
|
||||||
|
|
||||||
.o:
|
|
||||||
Create a relocatable object file. You can use this option if you
|
|
||||||
don't want to use the TinyGo build system or want to do other custom
|
|
||||||
things.
|
|
||||||
|
|
||||||
.ll:
|
|
||||||
Create textual LLVM IR, after optimization. This is mainly useful
|
|
||||||
for debugging.
|
|
||||||
|
|
||||||
.bc:
|
|
||||||
Create LLVM bitcode, after optimization. This may be useful for
|
|
||||||
debugging or for linking into other programs using LTO.
|
|
||||||
|
|
||||||
.hex:
|
|
||||||
Create an Intel HEX file to flash it to a microcontroller.
|
|
||||||
|
|
||||||
.bin:
|
|
||||||
Similar, but create a binary file.
|
|
||||||
|
|
||||||
.wasm:
|
|
||||||
Compile and link a WebAssembly file.
|
|
||||||
|
|
||||||
(all other) Compile and link the program into a regular executable. For
|
|
||||||
microcontrollers, it is common to use the .elf file extension to indicate a
|
|
||||||
linked ELF file is generated. For Linux, it is common to build binaries with no
|
|
||||||
extension at all.`
|
|
||||||
|
|
||||||
usageRun = `Run the program, either directly on the host or in an emulated environment
|
|
||||||
(depending on -target).`
|
|
||||||
|
|
||||||
usageFlash = `Flash the program to a microcontroller. Some common flags are described below.
|
|
||||||
|
|
||||||
-target={name}:
|
|
||||||
Specifies the type of microcontroller that is used. The name of the
|
|
||||||
microcontroller is given on the individual pages for each board type
|
|
||||||
listed under Microcontrollers
|
|
||||||
(https://tinygo.org/docs/reference/microcontrollers/).
|
|
||||||
Examples: "arduino-nano", "d1mini", "xiao".
|
|
||||||
|
|
||||||
-monitor:
|
|
||||||
Start the serial monitor (see below) immediately after
|
|
||||||
flashing. However, some microcontrollers need a split second
|
|
||||||
or two to configure the serial port after flashing, and
|
|
||||||
using the "-monitor" flag can fail because the serial
|
|
||||||
monitor starts too quickly. In that case, use the "tinygo
|
|
||||||
monitor" command explicitly.`
|
|
||||||
|
|
||||||
usageMonitor = `Start the serial monitor on the serial port that is connected to the
|
|
||||||
microcontroller. If there is only a single board attached to the host computer,
|
|
||||||
the default values for various options should be sufficient. In other
|
|
||||||
situations, particularly if you have multiple microcontrollers attached, some
|
|
||||||
parameters may need to be overridden using the following flags:
|
|
||||||
|
|
||||||
-port={port}:
|
|
||||||
If there are multiple microcontroller attached, an error
|
|
||||||
message will display a list of potential serial ports. The
|
|
||||||
appropriate port can be specified by this flag. On Linux,
|
|
||||||
the port will be something like /dev/ttyUSB0 or /dev/ttyACM1.
|
|
||||||
On MacOS, the port will look like /dev/cu.usbserial-1420. On
|
|
||||||
Windows, the port will be something like COM1 or COM31.
|
|
||||||
|
|
||||||
-baudrate={rate}:
|
|
||||||
The default baud rate is 115200. Boards using the AVR
|
|
||||||
processor (e.g. Arduino Nano, Arduino Mega 2560) use 9600
|
|
||||||
instead.
|
|
||||||
|
|
||||||
-target={name}:
|
|
||||||
If you have more than one microcontrollers attached, you can
|
|
||||||
sometimes just specify the target name and let tinygo
|
|
||||||
monitor figure out the port. Sometimes, this does not work
|
|
||||||
and you have to explicitly use the -port flag.
|
|
||||||
|
|
||||||
The serial monitor intercepts several control characters for its own use instead of sending them
|
|
||||||
to the microcontroller:
|
|
||||||
|
|
||||||
Control-C: terminates the tinygo monitor
|
|
||||||
Control-Z: suspends the tinygo monitor and drops back into shell
|
|
||||||
Control-\: terminates the tinygo monitor with a stack trace
|
|
||||||
Control-S: flow control, suspends output to the console
|
|
||||||
Control-Q: flow control, resumes output to the console
|
|
||||||
Control-@: thrown away by tinygo monitor
|
|
||||||
|
|
||||||
Note: If you are using os.Stdin on the microcontroller, you may find that a CR
|
|
||||||
character on the host computer (also known as Enter, ^M, or \r) is transmitted
|
|
||||||
to the microcontroller without conversion, so os.Stdin returns a \r character
|
|
||||||
instead of the expected \n (also known as ^J, NL, or LF) to indicate
|
|
||||||
end-of-line. You may be able to get around this problem by hitting Control-J in
|
|
||||||
tinygo monitor to transmit the \n end-of-line character.`
|
|
||||||
|
|
||||||
usageGdb = `Build the program, optionally flash it to a microcontroller if it is a remote
|
|
||||||
target, and drop into a GDB shell. From there you can set breakpoints, start the
|
|
||||||
program with "run" or "continue" ("run" for a local program, continue for
|
|
||||||
on-chip debugging), single-step, show a backtrace, break and resume the program
|
|
||||||
with Ctrl-C/"continue", etc. You may need to install extra tools (like openocd
|
|
||||||
and arm-none-eabi-gdb) to be able to do this. Also, you may need a dedicated
|
|
||||||
debugger to be able to debug certain boards if no debugger is integrated. Some
|
|
||||||
boards (like the BBC micro:bit and most professional evaluation boards) have an
|
|
||||||
integrated debugger.`
|
|
||||||
|
|
||||||
usageClean = `Clean the cache directory, normally stored in $HOME/.cache/tinygo. This is not
|
|
||||||
normally needed.`
|
|
||||||
|
|
||||||
usageHelp = `Print a short summary of the available commands, plus a list of command flags.`
|
|
||||||
usageVersion = `Print the version of the command and the version of the used $GOROOT.`
|
|
||||||
usageEnv = `Print a list of environment variables that affect TinyGo (as a shell script).
|
|
||||||
If one or more variable names are given as arguments, env prints the value of
|
|
||||||
each on a new line.`
|
|
||||||
|
|
||||||
usageDefault = `TinyGo is a Go compiler for small places.
|
|
||||||
version: %s
|
|
||||||
usage: %s <command> [arguments]
|
|
||||||
commands:
|
|
||||||
build: compile packages and dependencies
|
|
||||||
run: compile and run immediately
|
|
||||||
test: test packages
|
|
||||||
flash: compile and flash to the device
|
|
||||||
gdb: run/flash and immediately enter GDB
|
|
||||||
lldb: run/flash and immediately enter LLDB
|
|
||||||
monitor: open communication port
|
|
||||||
ports: list available serial ports
|
|
||||||
env: list environment variables used during build
|
|
||||||
list: run go list using the TinyGo root
|
|
||||||
clean: empty cache directory (%s)
|
|
||||||
targets: list targets
|
|
||||||
info: show info for specified target
|
|
||||||
version: show version
|
|
||||||
help: print this help text`
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
commandHelp = map[string]string{
|
|
||||||
"build": usageBuild,
|
|
||||||
"run": usageRun,
|
|
||||||
"flash": usageFlash,
|
|
||||||
"monitor": usageMonitor,
|
|
||||||
"gdb": usageGdb,
|
|
||||||
"clean": usageClean,
|
|
||||||
"help": usageHelp,
|
|
||||||
"version": usageVersion,
|
|
||||||
"env": usageEnv,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func usage(command string) {
|
func usage(command string) {
|
||||||
val, ok := commandHelp[command]
|
switch command {
|
||||||
if !ok {
|
default:
|
||||||
fmt.Fprintf(os.Stderr, usageDefault, goenv.Version(), os.Args[0], goenv.Get("GOCACHE"))
|
fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.")
|
||||||
|
fmt.Fprintln(os.Stderr, "version:", goenv.Version())
|
||||||
|
fmt.Fprintf(os.Stderr, "usage: %s <command> [arguments]\n", os.Args[0])
|
||||||
|
fmt.Fprintln(os.Stderr, "\ncommands:")
|
||||||
|
fmt.Fprintln(os.Stderr, " build: compile packages and dependencies")
|
||||||
|
fmt.Fprintln(os.Stderr, " run: compile and run immediately")
|
||||||
|
fmt.Fprintln(os.Stderr, " test: test packages")
|
||||||
|
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
|
||||||
|
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
||||||
|
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
||||||
|
fmt.Fprintln(os.Stderr, " monitor: open communication port")
|
||||||
|
fmt.Fprintln(os.Stderr, " ports: list available serial ports")
|
||||||
|
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
||||||
|
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
||||||
|
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
||||||
|
fmt.Fprintln(os.Stderr, " targets: list targets")
|
||||||
|
fmt.Fprintln(os.Stderr, " info: show info for specified target")
|
||||||
|
fmt.Fprintln(os.Stderr, " version: show version")
|
||||||
|
fmt.Fprintln(os.Stderr, " help: print this help text")
|
||||||
|
|
||||||
if flag.Parsed() {
|
if flag.Parsed() {
|
||||||
fmt.Fprintln(os.Stderr, "\nflags:")
|
fmt.Fprintln(os.Stderr, "\nflags:")
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintln(os.Stderr, "\nfor more details, see https://tinygo.org/docs/reference/usage/")
|
fmt.Fprintln(os.Stderr, "\nfor more details, see https://tinygo.org/docs/reference/usage/")
|
||||||
} else {
|
|
||||||
fmt.Fprintln(os.Stderr, val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCompilerError(err error) {
|
func handleCompilerError(err error) {
|
||||||
@@ -1439,20 +1330,19 @@ func (m globalValuesFlag) Set(value string) error {
|
|||||||
|
|
||||||
// parseGoLinkFlag parses the -ldflags parameter. Its primary purpose right now
|
// parseGoLinkFlag parses the -ldflags parameter. Its primary purpose right now
|
||||||
// is the -X flag, for setting the value of global string variables.
|
// is the -X flag, for setting the value of global string variables.
|
||||||
func parseGoLinkFlag(flagsString string) (map[string]map[string]string, string, error) {
|
func parseGoLinkFlag(flagsString string) (map[string]map[string]string, error) {
|
||||||
set := flag.NewFlagSet("link", flag.ExitOnError)
|
set := flag.NewFlagSet("link", flag.ExitOnError)
|
||||||
globalVarValues := make(globalValuesFlag)
|
globalVarValues := make(globalValuesFlag)
|
||||||
set.Var(globalVarValues, "X", "Set the value of the string variable to the given value.")
|
set.Var(globalVarValues, "X", "Set the value of the string variable to the given value.")
|
||||||
extLDFlags := set.String("extldflags", "", "additional flags to pass to external linker")
|
|
||||||
flags, err := shlex.Split(flagsString)
|
flags, err := shlex.Split(flagsString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = set.Parse(flags)
|
err = set.Parse(flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return map[string]map[string]string(globalVarValues), *extLDFlags, nil
|
return map[string]map[string]string(globalVarValues), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getListOfPackages returns a standard list of packages for a given list that might
|
// getListOfPackages returns a standard list of packages for a given list that might
|
||||||
@@ -1502,7 +1392,6 @@ func main() {
|
|||||||
var tags buildutil.TagsFlag
|
var tags buildutil.TagsFlag
|
||||||
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
||||||
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
||||||
buildMode := flag.String("buildmode", "", "build mode to use (default, c-shared)")
|
|
||||||
var stackSize uint64
|
var stackSize uint64
|
||||||
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
|
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
|
||||||
size, err := bytesize.Parse(s)
|
size, err := bytesize.Parse(s)
|
||||||
@@ -1572,7 +1461,6 @@ func main() {
|
|||||||
|
|
||||||
// Early command processing, before commands are interpreted by the Go flag
|
// Early command processing, before commands are interpreted by the Go flag
|
||||||
// library.
|
// library.
|
||||||
handleChdirFlag()
|
|
||||||
switch command {
|
switch command {
|
||||||
case "clang", "ld.lld", "wasm-ld":
|
case "clang", "ld.lld", "wasm-ld":
|
||||||
err := builder.RunTool(command, os.Args[2:]...)
|
err := builder.RunTool(command, os.Args[2:]...)
|
||||||
@@ -1585,7 +1473,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
flag.CommandLine.Parse(os.Args[2:])
|
flag.CommandLine.Parse(os.Args[2:])
|
||||||
globalVarValues, extLDFlags, err := parseGoLinkFlag(*ldflags)
|
globalVarValues, err := parseGoLinkFlag(*ldflags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -1611,7 +1499,6 @@ func main() {
|
|||||||
GOARM: goenv.Get("GOARM"),
|
GOARM: goenv.Get("GOARM"),
|
||||||
GOMIPS: goenv.Get("GOMIPS"),
|
GOMIPS: goenv.Get("GOMIPS"),
|
||||||
Target: *target,
|
Target: *target,
|
||||||
BuildMode: *buildMode,
|
|
||||||
StackSize: stackSize,
|
StackSize: stackSize,
|
||||||
Opt: *opt,
|
Opt: *opt,
|
||||||
GC: *gc,
|
GC: *gc,
|
||||||
@@ -1646,14 +1533,6 @@ func main() {
|
|||||||
options.PrintCommands = printCommand
|
options.PrintCommands = printCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
if extLDFlags != "" {
|
|
||||||
options.ExtLDFlags, err = shlex.Split(extLDFlags)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, "could not parse -extldflags:", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = options.Verify()
|
err = options.Verify()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err.Error())
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
@@ -2067,56 +1946,3 @@ type outputEntry struct {
|
|||||||
stderr bool
|
stderr bool
|
||||||
data []byte
|
data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleChdirFlag handles the -C flag before doing anything else.
|
|
||||||
// The -C flag must be the first flag on the command line, to make it easy to find
|
|
||||||
// even with commands that have custom flag parsing.
|
|
||||||
// handleChdirFlag handles the flag by chdir'ing to the directory
|
|
||||||
// and then removing that flag from the command line entirely.
|
|
||||||
//
|
|
||||||
// We have to handle the -C flag this way for two reasons:
|
|
||||||
//
|
|
||||||
// 1. Toolchain selection needs to be in the right directory to look for go.mod and go.work.
|
|
||||||
//
|
|
||||||
// 2. A toolchain switch later on reinvokes the new go command with the same arguments.
|
|
||||||
// The parent toolchain has already done the chdir; the child must not try to do it again.
|
|
||||||
|
|
||||||
func handleChdirFlag() {
|
|
||||||
used := 2 // b.c. command at os.Args[1]
|
|
||||||
if used >= len(os.Args) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var dir string
|
|
||||||
switch a := os.Args[used]; {
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
|
|
||||||
case a == "-C", a == "--C":
|
|
||||||
if used+1 >= len(os.Args) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dir = os.Args[used+1]
|
|
||||||
os.Args = slicesDelete(os.Args, used, used+2)
|
|
||||||
|
|
||||||
case strings.HasPrefix(a, "-C="), strings.HasPrefix(a, "--C="):
|
|
||||||
_, dir, _ = strings.Cut(a, "=")
|
|
||||||
os.Args = slicesDelete(os.Args, used, used+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.Chdir(dir); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, "cannot chdir:", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// go1.19 compatibility: lacks slices package
|
|
||||||
func slicesDelete[S ~[]E, E any](s S, i, j int) S {
|
|
||||||
_ = s[i:j:len(s)] // bounds check
|
|
||||||
|
|
||||||
if i == j {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(s[:i], s[j:]...)
|
|
||||||
}
|
|
||||||
|
|||||||
+36
-416
@@ -6,8 +6,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"io"
|
"io"
|
||||||
@@ -16,19 +14,16 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aykevl/go-wasm"
|
"github.com/aykevl/go-wasm"
|
||||||
"github.com/tetratelabs/wazero"
|
|
||||||
"github.com/tetratelabs/wazero/api"
|
|
||||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
|
||||||
"github.com/tetratelabs/wazero/sys"
|
|
||||||
"github.com/tinygo-org/tinygo/builder"
|
"github.com/tinygo-org/tinygo/builder"
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
"github.com/tinygo-org/tinygo/diagnostics"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -80,7 +75,6 @@ func TestBuild(t *testing.T) {
|
|||||||
"oldgo/",
|
"oldgo/",
|
||||||
"print.go",
|
"print.go",
|
||||||
"reflect.go",
|
"reflect.go",
|
||||||
"signal.go",
|
|
||||||
"slice.go",
|
"slice.go",
|
||||||
"sort.go",
|
"sort.go",
|
||||||
"stdlib.go",
|
"stdlib.go",
|
||||||
@@ -115,15 +109,10 @@ func TestBuild(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Debugging", func(t *testing.T) {
|
t.Run("Host", func(t *testing.T) {
|
||||||
for i := 0; i < 5; i++ {
|
t.Parallel()
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
runPlatTests(optionsFromTarget("", sema), tests, t)
|
||||||
options := optionsFromTarget("", sema)
|
|
||||||
runTest("alias.go", options, t, nil, nil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
return
|
|
||||||
|
|
||||||
// Test a few build options.
|
// Test a few build options.
|
||||||
t.Run("build-options", func(t *testing.T) {
|
t.Run("build-options", func(t *testing.T) {
|
||||||
@@ -224,7 +213,6 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
|||||||
// isWebAssembly := strings.HasPrefix(spec.Triple, "wasm")
|
// isWebAssembly := strings.HasPrefix(spec.Triple, "wasm")
|
||||||
isWASI := strings.HasPrefix(options.Target, "wasi")
|
isWASI := strings.HasPrefix(options.Target, "wasi")
|
||||||
isWebAssembly := isWASI || strings.HasPrefix(options.Target, "wasm") || (options.Target == "" && strings.HasPrefix(options.GOARCH, "wasm"))
|
isWebAssembly := isWASI || strings.HasPrefix(options.Target, "wasm") || (options.Target == "" && strings.HasPrefix(options.GOARCH, "wasm"))
|
||||||
isBaremetal := options.Target == "simavr" || options.Target == "cortex-m-qemu" || options.Target == "riscv-qemu"
|
|
||||||
|
|
||||||
for _, name := range tests {
|
for _, name := range tests {
|
||||||
if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") {
|
if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") {
|
||||||
@@ -289,13 +277,6 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isWebAssembly || isBaremetal || options.GOOS == "windows" {
|
|
||||||
switch name {
|
|
||||||
case "signal.go":
|
|
||||||
// Signals only work on POSIX-like systems.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
name := name // redefine to avoid race condition
|
name := name // redefine to avoid race condition
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
@@ -411,13 +392,17 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
// of the path.
|
// of the path.
|
||||||
path := TESTDATA + "/" + name
|
path := TESTDATA + "/" + name
|
||||||
// Get the expected output for this test.
|
// Get the expected output for this test.
|
||||||
expectedOutputPath := path[:len(path)-3] + ".txt"
|
txtpath := path[:len(path)-3] + ".txt"
|
||||||
pkgName := "./" + path
|
pkgName := "./" + path
|
||||||
if path[len(path)-1] == '/' {
|
if path[len(path)-1] == '/' {
|
||||||
expectedOutputPath = path + "out.txt"
|
txtpath = path + "out.txt"
|
||||||
options.Directory = path
|
options.Directory = path
|
||||||
pkgName = "."
|
pkgName = "."
|
||||||
}
|
}
|
||||||
|
expected, err := os.ReadFile(txtpath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("could not read expected output file:", err)
|
||||||
|
}
|
||||||
|
|
||||||
config, err := builder.NewConfig(&options)
|
config, err := builder.NewConfig(&options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -426,68 +411,23 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
|
|
||||||
// Build the test binary.
|
// Build the test binary.
|
||||||
stdout := &bytes.Buffer{}
|
stdout := &bytes.Buffer{}
|
||||||
_, fileExt := config.EmulatorFormat()
|
_, err = buildAndRun(pkgName, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
tmpdir := t.TempDir()
|
return cmd.Run()
|
||||||
result, err := builder.Build(pkgName, fileExt, tmpdir, config)
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("build failed:", err)
|
w := &bytes.Buffer{}
|
||||||
|
diagnostics.CreateDiagnostics(err).WriteTo(w, "")
|
||||||
|
for _, line := range strings.Split(strings.TrimRight(w.String(), "\n"), "\n") {
|
||||||
|
t.Log(line)
|
||||||
|
}
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := os.ReadFile(result.Executable)
|
// putchar() prints CRLF, convert it to LF.
|
||||||
if err != nil {
|
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
|
||||||
t.Fatal("failed to read executable:", err)
|
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows
|
||||||
}
|
|
||||||
hash := sha256.Sum256(data)
|
|
||||||
t.Logf("executable hash and size: %d %x", len(data), hash)
|
|
||||||
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
i := i
|
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
stdout := &bytes.Buffer{}
|
|
||||||
cmd := exec.Command(result.Executable)
|
|
||||||
cmd.Stdout = stdout
|
|
||||||
cmd.Stderr = stdout
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
t.Log("run error:", err)
|
|
||||||
}
|
|
||||||
checkOutput(t, expectedOutputPath, stdout.Bytes())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
//_, err = buildAndRun(pkgName, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
|
||||||
// data, err := os.ReadFile(result.Executable)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal("failed to read executable:", err)
|
|
||||||
// }
|
|
||||||
// hash := sha256.Sum256(data)
|
|
||||||
// t.Logf("executable hash and size: %d %x", len(data), hash)
|
|
||||||
|
|
||||||
// t.Log("command:", cmd)
|
|
||||||
// err = cmd.Run()
|
|
||||||
// if err == nil {
|
|
||||||
// t.Log(" error is nil!")
|
|
||||||
// } else {
|
|
||||||
// t.Log(" error:", err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
//})
|
|
||||||
//if err != nil {
|
|
||||||
// w := &bytes.Buffer{}
|
|
||||||
// diagnostics.CreateDiagnostics(err).WriteTo(w, "")
|
|
||||||
// for _, line := range strings.Split(strings.TrimRight(w.String(), "\n"), "\n") {
|
|
||||||
// t.Log(line)
|
|
||||||
// }
|
|
||||||
// if stdout.Len() != 0 {
|
|
||||||
// t.Logf("output:\n%s", stdout.String())
|
|
||||||
// }
|
|
||||||
// t.Fail()
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
actual := stdout.Bytes()
|
|
||||||
if config.EmulatorName() == "simavr" {
|
if config.EmulatorName() == "simavr" {
|
||||||
// Strip simavr log formatting.
|
// Strip simavr log formatting.
|
||||||
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
|
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
|
||||||
@@ -502,12 +442,17 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the command ran successfully.
|
// Check whether the command ran successfully.
|
||||||
|
fail := false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed to run:", err)
|
t.Log("failed to run:", err)
|
||||||
|
fail = true
|
||||||
|
} else if !bytes.Equal(expected, actual) {
|
||||||
|
t.Logf("output did not match (expected %d bytes, got %d bytes):", len(expected), len(actual))
|
||||||
|
t.Logf(string(Diff("expected", expected, "actual", actual)))
|
||||||
|
fail = true
|
||||||
}
|
}
|
||||||
checkOutput(t, expectedOutputPath, actual)
|
|
||||||
|
|
||||||
if t.Failed() {
|
if fail {
|
||||||
r := bufio.NewReader(bytes.NewReader(actual))
|
r := bufio.NewReader(bytes.NewReader(actual))
|
||||||
for {
|
for {
|
||||||
line, err := r.ReadString('\n')
|
line, err := r.ReadString('\n')
|
||||||
@@ -525,21 +470,20 @@ func TestWebAssembly(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
target string
|
|
||||||
panicStrategy string
|
panicStrategy string
|
||||||
imports []string
|
imports []string
|
||||||
}
|
}
|
||||||
for _, tc := range []testCase{
|
for _, tc := range []testCase{
|
||||||
// Test whether there really are no imports when using -panic=trap. This
|
// Test whether there really are no imports when using -panic=trap. This
|
||||||
// tests the bugfix for https://github.com/tinygo-org/tinygo/issues/4161.
|
// tests the bugfix for https://github.com/tinygo-org/tinygo/issues/4161.
|
||||||
{name: "panic-default", target: "wasip1", imports: []string{"wasi_snapshot_preview1.fd_write", "wasi_snapshot_preview1.random_get"}},
|
{name: "panic-default", imports: []string{"wasi_snapshot_preview1.fd_write"}},
|
||||||
{name: "panic-trap", target: "wasm-unknown", panicStrategy: "trap", imports: []string{}},
|
{name: "panic-trap", panicStrategy: "trap", imports: []string{}},
|
||||||
} {
|
} {
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
tmpdir := t.TempDir()
|
tmpdir := t.TempDir()
|
||||||
options := optionsFromTarget(tc.target, sema)
|
options := optionsFromTarget("wasi", sema)
|
||||||
options.PanicStrategy = tc.panicStrategy
|
options.PanicStrategy = tc.panicStrategy
|
||||||
config, err := builder.NewConfig(&options)
|
config, err := builder.NewConfig(&options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -571,7 +515,7 @@ func TestWebAssembly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !stringSlicesEqual(imports, tc.imports) {
|
if !slices.Equal(imports, tc.imports) {
|
||||||
t.Errorf("import list not as expected!\nexpected: %v\nactual: %v", tc.imports, imports)
|
t.Errorf("import list not as expected!\nexpected: %v\nactual: %v", tc.imports, imports)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -579,330 +523,6 @@ func TestWebAssembly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringSlicesEqual(s1, s2 []string) bool {
|
|
||||||
// We can use slices.Equal once we drop support for Go 1.20 (it was added in
|
|
||||||
// Go 1.21).
|
|
||||||
if len(s1) != len(s2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, s := range s1 {
|
|
||||||
if s != s2[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWasmExport(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
name string
|
|
||||||
target string
|
|
||||||
buildMode string
|
|
||||||
scheduler string
|
|
||||||
file string
|
|
||||||
noOutput bool
|
|
||||||
command bool // call _start (command mode) instead of _initialize
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []testCase{
|
|
||||||
// "command mode" WASI
|
|
||||||
{
|
|
||||||
name: "WASIp1-command",
|
|
||||||
target: "wasip1",
|
|
||||||
command: true,
|
|
||||||
},
|
|
||||||
// "reactor mode" WASI (with -buildmode=c-shared)
|
|
||||||
{
|
|
||||||
name: "WASIp1-reactor",
|
|
||||||
target: "wasip1",
|
|
||||||
buildMode: "c-shared",
|
|
||||||
},
|
|
||||||
// Make sure reactor mode also works without a scheduler.
|
|
||||||
{
|
|
||||||
name: "WASIp1-reactor-noscheduler",
|
|
||||||
target: "wasip1",
|
|
||||||
buildMode: "c-shared",
|
|
||||||
scheduler: "none",
|
|
||||||
file: "wasmexport-noscheduler.go",
|
|
||||||
},
|
|
||||||
// Test -target=wasm-unknown with the default build mode (which is
|
|
||||||
// c-shared).
|
|
||||||
{
|
|
||||||
name: "wasm-unknown-reactor",
|
|
||||||
target: "wasm-unknown",
|
|
||||||
file: "wasmexport-noscheduler.go",
|
|
||||||
noOutput: true, // wasm-unknown cannot produce output
|
|
||||||
},
|
|
||||||
// Test -target=wasm-unknown with -buildmode=default, which makes it run
|
|
||||||
// in command mode.
|
|
||||||
{
|
|
||||||
name: "wasm-unknown-command",
|
|
||||||
target: "wasm-unknown",
|
|
||||||
buildMode: "default",
|
|
||||||
file: "wasmexport-noscheduler.go",
|
|
||||||
noOutput: true, // wasm-unknown cannot produce output
|
|
||||||
command: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Build the wasm binary.
|
|
||||||
tmpdir := t.TempDir()
|
|
||||||
options := optionsFromTarget(tc.target, sema)
|
|
||||||
options.BuildMode = tc.buildMode
|
|
||||||
options.Scheduler = tc.scheduler
|
|
||||||
buildConfig, err := builder.NewConfig(&options)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
filename := "wasmexport.go"
|
|
||||||
if tc.file != "" {
|
|
||||||
filename = tc.file
|
|
||||||
}
|
|
||||||
result, err := builder.Build("testdata/"+filename, ".wasm", tmpdir, buildConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("failed to build binary:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the wasm binary back into memory.
|
|
||||||
data, err := os.ReadFile(result.Binary)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("could not read wasm binary: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the wazero runtime.
|
|
||||||
output := &bytes.Buffer{}
|
|
||||||
ctx := context.Background()
|
|
||||||
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter())
|
|
||||||
defer r.Close(ctx)
|
|
||||||
config := wazero.NewModuleConfig().
|
|
||||||
WithStdout(output).WithStderr(output).
|
|
||||||
WithStartFunctions()
|
|
||||||
|
|
||||||
// Prepare for testing.
|
|
||||||
var mod api.Module
|
|
||||||
mustCall := func(results []uint64, err error) []uint64 {
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to run function:", err)
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
checkResult := func(name string, results []uint64, expected []uint64) {
|
|
||||||
if len(results) != len(expected) {
|
|
||||||
t.Errorf("%s: expected %v but got %v", name, expected, results)
|
|
||||||
}
|
|
||||||
for i, result := range results {
|
|
||||||
if result != expected[i] {
|
|
||||||
t.Errorf("%s: expected %v but got %v", name, expected, results)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runTests := func() {
|
|
||||||
// Test an exported function without params or return value.
|
|
||||||
checkResult("hello()", mustCall(mod.ExportedFunction("hello").Call(ctx)), nil)
|
|
||||||
|
|
||||||
// Test that we can call an exported function more than once.
|
|
||||||
checkResult("add(3, 5)", mustCall(mod.ExportedFunction("add").Call(ctx, 3, 5)), []uint64{8})
|
|
||||||
checkResult("add(7, 9)", mustCall(mod.ExportedFunction("add").Call(ctx, 7, 9)), []uint64{16})
|
|
||||||
checkResult("add(6, 1)", mustCall(mod.ExportedFunction("add").Call(ctx, 6, 1)), []uint64{7})
|
|
||||||
|
|
||||||
// Test that imported functions can call exported functions
|
|
||||||
// again.
|
|
||||||
checkResult("reentrantCall(2, 3)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 2, 3)), []uint64{5})
|
|
||||||
checkResult("reentrantCall(1, 8)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 1, 8)), []uint64{9})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add wasip1 module.
|
|
||||||
wasi_snapshot_preview1.MustInstantiate(ctx, r)
|
|
||||||
|
|
||||||
// Add custom "tester" module.
|
|
||||||
callOutside := func(a, b int32) int32 {
|
|
||||||
results, err := mod.ExportedFunction("add").Call(ctx, uint64(a), uint64(b))
|
|
||||||
if err != nil {
|
|
||||||
t.Error("could not call exported add function:", err)
|
|
||||||
}
|
|
||||||
return int32(results[0])
|
|
||||||
}
|
|
||||||
callTestMain := func() {
|
|
||||||
runTests()
|
|
||||||
}
|
|
||||||
builder := r.NewHostModuleBuilder("tester")
|
|
||||||
builder.NewFunctionBuilder().WithFunc(callOutside).Export("callOutside")
|
|
||||||
builder.NewFunctionBuilder().WithFunc(callTestMain).Export("callTestMain")
|
|
||||||
_, err = builder.Instantiate(ctx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse and instantiate the wasm.
|
|
||||||
mod, err = r.InstantiateWithConfig(ctx, data, config)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("could not instantiate wasm module:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the module and run the tests.
|
|
||||||
if tc.command {
|
|
||||||
// Call _start (the entry point), which calls
|
|
||||||
// tester.callTestMain, which then runs all the tests.
|
|
||||||
_, err := mod.ExportedFunction("_start").Call(ctx)
|
|
||||||
if err != nil {
|
|
||||||
if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() == 0 {
|
|
||||||
// Exited with code 0. Nothing to worry about.
|
|
||||||
} else {
|
|
||||||
t.Error("failed to run _start:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Run the _initialize call, because this is reactor mode wasm.
|
|
||||||
mustCall(mod.ExportedFunction("_initialize").Call(ctx))
|
|
||||||
runTests()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the output matches the expected output.
|
|
||||||
// (Skip this for wasm-unknown because it can't produce output).
|
|
||||||
if !tc.noOutput {
|
|
||||||
checkOutput(t, "testdata/wasmexport.txt", output.Bytes())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test js.FuncOf (for syscall/js).
|
|
||||||
// This test might be extended in the future to cover more cases in syscall/js.
|
|
||||||
func TestWasmFuncOf(t *testing.T) {
|
|
||||||
// Build the wasm binary.
|
|
||||||
tmpdir := t.TempDir()
|
|
||||||
options := optionsFromTarget("wasm", sema)
|
|
||||||
buildConfig, err := builder.NewConfig(&options)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
result, err := builder.Build("testdata/wasmfunc.go", ".wasm", tmpdir, buildConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("failed to build binary:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the resulting binary using NodeJS.
|
|
||||||
output := &bytes.Buffer{}
|
|
||||||
cmd := exec.Command("node", "testdata/wasmfunc.js", result.Binary, buildConfig.BuildMode())
|
|
||||||
cmd.Stdout = output
|
|
||||||
cmd.Stderr = output
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to run node:", err)
|
|
||||||
}
|
|
||||||
checkOutput(t, "testdata/wasmfunc.txt", output.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test //go:wasmexport in JavaScript (using NodeJS).
|
|
||||||
func TestWasmExportJS(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
type testCase struct {
|
|
||||||
name string
|
|
||||||
buildMode string
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []testCase{
|
|
||||||
{name: "default"},
|
|
||||||
{name: "c-shared", buildMode: "c-shared"},
|
|
||||||
}
|
|
||||||
for _, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
// Build the wasm binary.
|
|
||||||
tmpdir := t.TempDir()
|
|
||||||
options := optionsFromTarget("wasm", sema)
|
|
||||||
options.BuildMode = tc.buildMode
|
|
||||||
buildConfig, err := builder.NewConfig(&options)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
result, err := builder.Build("testdata/wasmexport-noscheduler.go", ".wasm", tmpdir, buildConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("failed to build binary:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the resulting binary using NodeJS.
|
|
||||||
output := &bytes.Buffer{}
|
|
||||||
cmd := exec.Command("node", "testdata/wasmexport.js", result.Binary, buildConfig.BuildMode())
|
|
||||||
cmd.Stdout = output
|
|
||||||
cmd.Stderr = output
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to run node:", err)
|
|
||||||
}
|
|
||||||
checkOutput(t, "testdata/wasmexport.txt", output.Bytes())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test whether Go.run() (in wasm_exec.js) normally returns and returns the
|
|
||||||
// right exit code.
|
|
||||||
func TestWasmExit(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
name string
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []testCase{
|
|
||||||
{name: "normal", output: "exit code: 0\n"},
|
|
||||||
{name: "exit-0", output: "exit code: 0\n"},
|
|
||||||
{name: "exit-0-sleep", output: "slept\nexit code: 0\n"},
|
|
||||||
{name: "exit-1", output: "exit code: 1\n"},
|
|
||||||
{name: "exit-1-sleep", output: "slept\nexit code: 1\n"},
|
|
||||||
}
|
|
||||||
for _, tc := range tests {
|
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
options := optionsFromTarget("wasm", sema)
|
|
||||||
buildConfig, err := builder.NewConfig(&options)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
buildConfig.Target.Emulator = "node testdata/wasmexit.js {}"
|
|
||||||
output := &bytes.Buffer{}
|
|
||||||
_, err = buildAndRun("testdata/wasmexit.go", buildConfig, output, []string{tc.name}, nil, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
|
||||||
return cmd.Run()
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
expected := "wasmexit test: " + tc.name + "\n" + tc.output
|
|
||||||
checkOutputData(t, []byte(expected), output.Bytes())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the output of a test equals the expected output.
|
|
||||||
func checkOutput(t *testing.T, filename string, actual []byte) {
|
|
||||||
expectedOutput, err := os.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("could not read output file:", err)
|
|
||||||
}
|
|
||||||
checkOutputData(t, expectedOutput, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkOutputData(t *testing.T, expectedOutput, actual []byte) {
|
|
||||||
expectedOutput = bytes.ReplaceAll(expectedOutput, []byte("\r\n"), []byte("\n"))
|
|
||||||
actual = bytes.ReplaceAll(actual, []byte("\r\n"), []byte("\n"))
|
|
||||||
|
|
||||||
if !bytes.Equal(actual, expectedOutput) {
|
|
||||||
t.Errorf("output did not match (expected %d bytes, got %d bytes):", len(expectedOutput), len(actual))
|
|
||||||
t.Error(string(Diff("expected", expectedOutput, "actual", actual)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTest(t *testing.T) {
|
func TestTest(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -1,185 +0,0 @@
|
|||||||
package macos
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Exported symbols copied from Big Go, but stripped of functionality.
|
|
||||||
// Allows building of crypto/x509 on macOS.
|
|
||||||
|
|
||||||
const (
|
|
||||||
ErrSecCertificateExpired = -67818
|
|
||||||
ErrSecHostNameMismatch = -67602
|
|
||||||
ErrSecNotTrusted = -67843
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrNoTrustSettings = errors.New("no trust settings found")
|
|
||||||
var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO
|
|
||||||
var SecPolicyOid = StringToCFString("SecPolicyOid")
|
|
||||||
var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy")
|
|
||||||
var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString")
|
|
||||||
var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult")
|
|
||||||
|
|
||||||
func CFArrayAppendValue(array CFRef, val CFRef) {}
|
|
||||||
|
|
||||||
func CFArrayGetCount(array CFRef) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFDataGetBytePtr(data CFRef) uintptr {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFDataGetLength(data CFRef) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFDataToSlice(data CFRef) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFEqual(a, b CFRef) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFErrorGetCode(errRef CFRef) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFNumberGetValue(num CFRef) (int32, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFRelease(ref CFRef) {}
|
|
||||||
|
|
||||||
func CFStringToString(ref CFRef) string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReleaseCFArray(array CFRef) {}
|
|
||||||
|
|
||||||
func SecCertificateCopyData(cert CFRef) ([]byte, error) {
|
|
||||||
return nil, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustGetCertificateCount(trustObj CFRef) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) {
|
|
||||||
return 0, 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error {
|
|
||||||
return errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
type CFRef uintptr
|
|
||||||
|
|
||||||
func BytesToCFData(b []byte) CFRef {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFArrayCreateMutable() CFRef {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFDateCreate(seconds float64) CFRef {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFErrorCopyDescription(errRef CFRef) CFRef {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecCertificateCreateWithData(b []byte) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecPolicyCreateSSL(name string) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustEvaluate(trustObj CFRef) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TimeToCFDateRef(t time.Time) CFRef {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CFString CFRef
|
|
||||||
|
|
||||||
func StringToCFString(s string) CFString {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type OSStatus struct {
|
|
||||||
// Has unexported fields.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s OSStatus) Error() string
|
|
||||||
|
|
||||||
type SecTrustResultType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SecTrustResultInvalid SecTrustResultType = iota
|
|
||||||
SecTrustResultProceed
|
|
||||||
SecTrustResultConfirm // deprecated
|
|
||||||
SecTrustResultDeny
|
|
||||||
SecTrustResultUnspecified
|
|
||||||
SecTrustResultRecoverableTrustFailure
|
|
||||||
SecTrustResultFatalTrustFailure
|
|
||||||
SecTrustResultOtherError
|
|
||||||
)
|
|
||||||
|
|
||||||
type SecTrustSettingsDomain int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SecTrustSettingsDomainUser SecTrustSettingsDomain = iota
|
|
||||||
SecTrustSettingsDomainAdmin
|
|
||||||
SecTrustSettingsDomainSystem
|
|
||||||
)
|
|
||||||
|
|
||||||
type SecTrustSettingsResult int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SecTrustSettingsResultInvalid SecTrustSettingsResult = iota
|
|
||||||
SecTrustSettingsResultTrustRoot
|
|
||||||
SecTrustSettingsResultTrustAsRoot
|
|
||||||
SecTrustSettingsResultDeny
|
|
||||||
SecTrustSettingsResultUnspecified
|
|
||||||
)
|
|
||||||
@@ -30,8 +30,3 @@ func (littleEndian) AppendUint16(b []byte, v uint16) []byte {
|
|||||||
func (littleEndian) Uint32(b []byte) uint32 {
|
func (littleEndian) Uint32(b []byte) uint32 {
|
||||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||||
}
|
}
|
||||||
|
|
||||||
func (littleEndian) Uint64(b []byte) uint64 {
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
|
||||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-28
@@ -2,11 +2,6 @@ package cm
|
|||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
// AnyInteger is a type constraint for any integer type.
|
|
||||||
type AnyInteger interface {
|
|
||||||
~int | ~uint | ~uintptr | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 | ~int64 | ~uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reinterpret reinterprets the bits of type From into type T.
|
// Reinterpret reinterprets the bits of type From into type T.
|
||||||
// Will panic if the size of From is smaller than the size of To.
|
// Will panic if the size of From is smaller than the size of To.
|
||||||
func Reinterpret[T, From any](from From) (to T) {
|
func Reinterpret[T, From any](from From) (to T) {
|
||||||
@@ -24,19 +19,19 @@ func LowerString[S ~string](s S) (*byte, uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LiftString lifts Core WebAssembly types into a [string].
|
// LiftString lifts Core WebAssembly types into a [string].
|
||||||
func LiftString[T ~string, Data unsafe.Pointer | uintptr | *uint8, Len AnyInteger](data Data, len Len) T {
|
func LiftString[T ~string, Data unsafe.Pointer | uintptr | *uint8, Len uint | uintptr | uint32 | uint64](data Data, len Len) T {
|
||||||
return T(unsafe.String((*uint8)(unsafe.Pointer(data)), int(len)))
|
return T(unsafe.String((*uint8)(unsafe.Pointer(data)), int(len)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LowerList lowers a [List] into a pair of Core WebAssembly types.
|
// LowerList lowers a [List] into a pair of Core WebAssembly types.
|
||||||
func LowerList[L AnyList[T], T any](list L) (*T, uint32) {
|
func LowerList[L ~struct{ list[T] }, T any](list L) (*T, uint32) {
|
||||||
l := (*List[T])(unsafe.Pointer(&list))
|
l := (*List[T])(unsafe.Pointer(&list))
|
||||||
return l.data, uint32(l.len)
|
return l.data, uint32(l.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LiftList lifts Core WebAssembly types into a [List].
|
// LiftList lifts Core WebAssembly types into a [List].
|
||||||
func LiftList[L AnyList[T], T any, Data unsafe.Pointer | uintptr | *T, Len AnyInteger](data Data, len Len) L {
|
func LiftList[L List[T], T any, Data unsafe.Pointer | uintptr | *T, Len uint | uintptr | uint32 | uint64](data Data, len Len) L {
|
||||||
return L(NewList((*T)(unsafe.Pointer(data)), len))
|
return L(NewList((*T)(unsafe.Pointer(data)), uint(len)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BoolToU32 converts a value whose underlying type is [bool] into a [uint32].
|
// BoolToU32 converts a value whose underlying type is [bool] into a [uint32].
|
||||||
@@ -89,25 +84,6 @@ func F64ToU64(v float64) uint64 { return *(*uint64)(unsafe.Pointer(&v)) }
|
|||||||
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
|
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
|
||||||
func U64ToF64(v uint64) float64 { return *(*float64)(unsafe.Pointer(&v)) }
|
func U64ToF64(v uint64) float64 { return *(*float64)(unsafe.Pointer(&v)) }
|
||||||
|
|
||||||
// F32ToU64 maps the bits of a [float32] into a [uint64].
|
|
||||||
// Used to lower a [float32] into a Core WebAssembly i64 when required by the [Canonical ABI].
|
|
||||||
//
|
|
||||||
// [float32]: https://pkg.go.dev/builtin#float32
|
|
||||||
// [uint64]: https://pkg.go.dev/builtin#uint64
|
|
||||||
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
|
|
||||||
func F32ToU64(v float32) uint64 { return uint64(*(*uint32)(unsafe.Pointer(&v))) }
|
|
||||||
|
|
||||||
// U64ToF32 maps the bits of a [uint64] into a [float32].
|
|
||||||
// Used to lift a Core WebAssembly i64 into a [float32] when required by the [Canonical ABI].
|
|
||||||
//
|
|
||||||
// [uint64]: https://pkg.go.dev/builtin#uint64
|
|
||||||
// [float32]: https://pkg.go.dev/builtin#float32
|
|
||||||
// [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
|
|
||||||
func U64ToF32(v uint64) float32 {
|
|
||||||
truncated := uint32(v)
|
|
||||||
return *(*float32)(unsafe.Pointer(&truncated))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PointerToU32 converts a pointer of type *T into a [uint32].
|
// PointerToU32 converts a pointer of type *T into a [uint32].
|
||||||
// Used to lower a pointer into a Core WebAssembly i32 as specified in the [Canonical ABI].
|
// Used to lower a pointer into a Core WebAssembly i32 as specified in the [Canonical ABI].
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
//go:build !go1.23
|
|
||||||
|
|
||||||
package cm
|
|
||||||
|
|
||||||
// HostLayout marks a struct as using host memory layout.
|
|
||||||
// See [structs.HostLayout] in Go 1.23 or later.
|
|
||||||
type HostLayout struct {
|
|
||||||
_ hostLayout // prevent accidental conversion with plain struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type hostLayout struct{}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
//go:build go1.23
|
|
||||||
|
|
||||||
package cm
|
|
||||||
|
|
||||||
import "structs"
|
|
||||||
|
|
||||||
// HostLayout marks a struct as using host memory layout.
|
|
||||||
// See [structs.HostLayout] in Go 1.23 or later.
|
|
||||||
type HostLayout = structs.HostLayout
|
|
||||||
+8
-20
@@ -4,25 +4,14 @@ import "unsafe"
|
|||||||
|
|
||||||
// List represents a Component Model list.
|
// List represents a Component Model list.
|
||||||
// The binary representation of list<T> is similar to a Go slice minus the cap field.
|
// The binary representation of list<T> is similar to a Go slice minus the cap field.
|
||||||
type List[T any] struct {
|
type List[T any] struct{ list[T] }
|
||||||
_ HostLayout
|
|
||||||
list[T]
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnyList is a type constraint for generic functions that accept any [List] type.
|
|
||||||
type AnyList[T any] interface {
|
|
||||||
~struct {
|
|
||||||
_ HostLayout
|
|
||||||
list[T]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewList returns a List[T] from data and len.
|
// NewList returns a List[T] from data and len.
|
||||||
func NewList[T any, Len AnyInteger](data *T, len Len) List[T] {
|
func NewList[T any](data *T, len uint) List[T] {
|
||||||
return List[T]{
|
return List[T]{
|
||||||
list: list[T]{
|
list[T]{
|
||||||
data: data,
|
data: data,
|
||||||
len: uintptr(len),
|
len: len,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,16 +20,15 @@ func NewList[T any, Len AnyInteger](data *T, len Len) List[T] {
|
|||||||
// The underlying slice data is not copied, and the resulting List points at the
|
// The underlying slice data is not copied, and the resulting List points at the
|
||||||
// same array storage as the slice.
|
// same array storage as the slice.
|
||||||
func ToList[S ~[]T, T any](s S) List[T] {
|
func ToList[S ~[]T, T any](s S) List[T] {
|
||||||
return NewList[T](unsafe.SliceData([]T(s)), uintptr(len(s)))
|
return NewList[T](unsafe.SliceData([]T(s)), uint(len(s)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// list represents the internal representation of a Component Model list.
|
// list represents the internal representation of a Component Model list.
|
||||||
// It is intended to be embedded in a [List], so embedding types maintain
|
// It is intended to be embedded in a [List], so embedding types maintain
|
||||||
// the methods defined on this type.
|
// the methods defined on this type.
|
||||||
type list[T any] struct {
|
type list[T any] struct {
|
||||||
_ HostLayout
|
|
||||||
data *T
|
data *T
|
||||||
len uintptr
|
len uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns a Go slice representing the List.
|
// Slice returns a Go slice representing the List.
|
||||||
@@ -54,7 +42,7 @@ func (l list[T]) Data() *T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the length of the list.
|
// Len returns the length of the list.
|
||||||
// TODO: should this return an int instead of a uintptr?
|
// TODO: should this return an int instead of a uint?
|
||||||
func (l list[T]) Len() uintptr {
|
func (l list[T]) Len() uint {
|
||||||
return l.len
|
return l.len
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ package cm
|
|||||||
// Option represents a Component Model [option<T>] type.
|
// Option represents a Component Model [option<T>] type.
|
||||||
//
|
//
|
||||||
// [option<T>]: https://component-model.bytecodealliance.org/design/wit.html#options
|
// [option<T>]: https://component-model.bytecodealliance.org/design/wit.html#options
|
||||||
type Option[T any] struct {
|
type Option[T any] struct{ option[T] }
|
||||||
_ HostLayout
|
|
||||||
option[T]
|
|
||||||
}
|
|
||||||
|
|
||||||
// None returns an [Option] representing the none case,
|
// None returns an [Option] representing the none case,
|
||||||
// equivalent to the zero value.
|
// equivalent to the zero value.
|
||||||
@@ -17,7 +14,7 @@ func None[T any]() Option[T] {
|
|||||||
// Some returns an [Option] representing the some case.
|
// Some returns an [Option] representing the some case.
|
||||||
func Some[T any](v T) Option[T] {
|
func Some[T any](v T) Option[T] {
|
||||||
return Option[T]{
|
return Option[T]{
|
||||||
option: option[T]{
|
option[T]{
|
||||||
isSome: true,
|
isSome: true,
|
||||||
some: v,
|
some: v,
|
||||||
},
|
},
|
||||||
@@ -28,7 +25,6 @@ func Some[T any](v T) Option[T] {
|
|||||||
// The first byte is a bool representing none or some,
|
// The first byte is a bool representing none or some,
|
||||||
// followed by storage for the associated type T.
|
// followed by storage for the associated type T.
|
||||||
type option[T any] struct {
|
type option[T any] struct {
|
||||||
_ HostLayout
|
|
||||||
isSome bool
|
isSome bool
|
||||||
some T
|
some T
|
||||||
}
|
}
|
||||||
@@ -46,14 +42,3 @@ func (o *option[T]) Some() *T {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value returns T if o represents the some case,
|
|
||||||
// or the zero value of T if o represents the none case.
|
|
||||||
// This does not have a pointer receiver, so it can be chained.
|
|
||||||
func (o option[T]) Value() T {
|
|
||||||
if !o.isSome {
|
|
||||||
var zero T
|
|
||||||
return zero
|
|
||||||
}
|
|
||||||
return o.some
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,22 +17,10 @@ type BoolResult bool
|
|||||||
// Result represents a result sized to hold the Shape type.
|
// Result represents a result sized to hold the Shape type.
|
||||||
// The size of the Shape type must be greater than or equal to the size of OK and Err types.
|
// The size of the Shape type must be greater than or equal to the size of OK and Err types.
|
||||||
// For results with two zero-length types, use [BoolResult].
|
// For results with two zero-length types, use [BoolResult].
|
||||||
type Result[Shape, OK, Err any] struct {
|
type Result[Shape, OK, Err any] struct{ result[Shape, OK, Err] }
|
||||||
_ HostLayout
|
|
||||||
result[Shape, OK, Err]
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnyResult is a type constraint for generic functions that accept any [Result] type.
|
|
||||||
type AnyResult[Shape, OK, Err any] interface {
|
|
||||||
~struct {
|
|
||||||
_ HostLayout
|
|
||||||
result[Shape, OK, Err]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// result represents the internal representation of a Component Model result type.
|
// result represents the internal representation of a Component Model result type.
|
||||||
type result[Shape, OK, Err any] struct {
|
type result[Shape, OK, Err any] struct {
|
||||||
_ HostLayout
|
|
||||||
isErr bool
|
isErr bool
|
||||||
_ [0]OK
|
_ [0]OK
|
||||||
_ [0]Err
|
_ [0]Err
|
||||||
@@ -71,16 +59,6 @@ func (r *result[Shape, OK, Err]) Err() *Err {
|
|||||||
return (*Err)(unsafe.Pointer(&r.data))
|
return (*Err)(unsafe.Pointer(&r.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result returns (OK, zero value of Err, false) if r represents the OK case,
|
|
||||||
// or (zero value of OK, Err, true) if r represents the error case.
|
|
||||||
// This does not have a pointer receiver, so it can be chained.
|
|
||||||
func (r result[Shape, OK, Err]) Result() (ok OK, err Err, isErr bool) {
|
|
||||||
if r.isErr {
|
|
||||||
return ok, *(*Err)(unsafe.Pointer(&r.data)), true
|
|
||||||
}
|
|
||||||
return *(*OK)(unsafe.Pointer(&r.data)), err, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is sized so it can be inlined and optimized away.
|
// This function is sized so it can be inlined and optimized away.
|
||||||
func (r *result[Shape, OK, Err]) validate() {
|
func (r *result[Shape, OK, Err]) validate() {
|
||||||
var shape Shape
|
var shape Shape
|
||||||
@@ -110,8 +88,8 @@ func (r *result[Shape, OK, Err]) validate() {
|
|||||||
|
|
||||||
// OK returns an OK result with shape Shape and type OK and Err.
|
// OK returns an OK result with shape Shape and type OK and Err.
|
||||||
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
|
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
|
||||||
func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
|
func OK[R ~struct{ result[Shape, OK, Err] }, Shape, OK, Err any](ok OK) R {
|
||||||
var r Result[Shape, OK, Err]
|
var r struct{ result[Shape, OK, Err] }
|
||||||
r.validate()
|
r.validate()
|
||||||
r.isErr = ResultOK
|
r.isErr = ResultOK
|
||||||
*((*OK)(unsafe.Pointer(&r.data))) = ok
|
*((*OK)(unsafe.Pointer(&r.data))) = ok
|
||||||
@@ -120,8 +98,8 @@ func OK[R AnyResult[Shape, OK, Err], Shape, OK, Err any](ok OK) R {
|
|||||||
|
|
||||||
// Err returns an error result with shape Shape and type OK and Err.
|
// Err returns an error result with shape Shape and type OK and Err.
|
||||||
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
|
// Pass Result[OK, OK, Err] or Result[Err, OK, Err] as the first type argument.
|
||||||
func Err[R AnyResult[Shape, OK, Err], Shape, OK, Err any](err Err) R {
|
func Err[R ~struct{ result[Shape, OK, Err] }, Shape, OK, Err any](err Err) R {
|
||||||
var r Result[Shape, OK, Err]
|
var r struct{ result[Shape, OK, Err] }
|
||||||
r.validate()
|
r.validate()
|
||||||
r.isErr = ResultErr
|
r.isErr = ResultErr
|
||||||
*((*Err)(unsafe.Pointer(&r.data))) = err
|
*((*Err)(unsafe.Pointer(&r.data))) = err
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ package cm
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple[T0, T1 any] struct {
|
type Tuple[T0, T1 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
}
|
}
|
||||||
@@ -13,7 +12,6 @@ type Tuple[T0, T1 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple3[T0, T1, T2 any] struct {
|
type Tuple3[T0, T1, T2 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -23,7 +21,6 @@ type Tuple3[T0, T1, T2 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple4[T0, T1, T2, T3 any] struct {
|
type Tuple4[T0, T1, T2, T3 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -34,7 +31,6 @@ type Tuple4[T0, T1, T2, T3 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple5[T0, T1, T2, T3, T4 any] struct {
|
type Tuple5[T0, T1, T2, T3, T4 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -46,7 +42,6 @@ type Tuple5[T0, T1, T2, T3, T4 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple6[T0, T1, T2, T3, T4, T5 any] struct {
|
type Tuple6[T0, T1, T2, T3, T4, T5 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -59,7 +54,6 @@ type Tuple6[T0, T1, T2, T3, T4, T5 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple7[T0, T1, T2, T3, T4, T5, T6 any] struct {
|
type Tuple7[T0, T1, T2, T3, T4, T5, T6 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -73,7 +67,6 @@ type Tuple7[T0, T1, T2, T3, T4, T5, T6 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] struct {
|
type Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -88,7 +81,6 @@ type Tuple8[T0, T1, T2, T3, T4, T5, T6, T7 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] struct {
|
type Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -104,7 +96,6 @@ type Tuple9[T0, T1, T2, T3, T4, T5, T6, T7, T8 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {
|
type Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -121,7 +112,6 @@ type Tuple10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
|
type Tuple11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -139,7 +129,6 @@ type Tuple11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {
|
type Tuple12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -158,7 +147,6 @@ type Tuple12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {
|
type Tuple13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -178,7 +166,6 @@ type Tuple13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] struct {
|
type Tuple14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -199,7 +186,6 @@ type Tuple14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] str
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any] struct {
|
type Tuple15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
@@ -221,7 +207,6 @@ type Tuple15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any
|
|||||||
//
|
//
|
||||||
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
// [Component Model tuple]: https://component-model.bytecodealliance.org/design/wit.html#tuples
|
||||||
type Tuple16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any] struct {
|
type Tuple16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any] struct {
|
||||||
_ HostLayout
|
|
||||||
F0 T0
|
F0 T0
|
||||||
F1 T1
|
F1 T1
|
||||||
F2 T2
|
F2 T2
|
||||||
|
|||||||
@@ -12,18 +12,7 @@ type Discriminant interface {
|
|||||||
// Variant represents a loosely-typed Component Model variant.
|
// Variant represents a loosely-typed Component Model variant.
|
||||||
// Shape and Align must be non-zero sized types. To create a variant with no associated
|
// Shape and Align must be non-zero sized types. To create a variant with no associated
|
||||||
// types, use an enum.
|
// types, use an enum.
|
||||||
type Variant[Tag Discriminant, Shape, Align any] struct {
|
type Variant[Tag Discriminant, Shape, Align any] struct{ variant[Tag, Shape, Align] }
|
||||||
_ HostLayout
|
|
||||||
variant[Tag, Shape, Align]
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnyVariant is a type constraint for generic functions that accept any [Variant] type.
|
|
||||||
type AnyVariant[Tag Discriminant, Shape, Align any] interface {
|
|
||||||
~struct {
|
|
||||||
_ HostLayout
|
|
||||||
variant[Tag, Shape, Align]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVariant returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,
|
// NewVariant returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,
|
||||||
// aligned to type Align, with a value of type T.
|
// aligned to type Align, with a value of type T.
|
||||||
@@ -37,7 +26,7 @@ func NewVariant[Tag Discriminant, Shape, Align any, T any](tag Tag, data T) Vari
|
|||||||
|
|
||||||
// New returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,
|
// New returns a [Variant] with tag of type Disc, storage and GC shape of type Shape,
|
||||||
// aligned to type Align, with a value of type T.
|
// aligned to type Align, with a value of type T.
|
||||||
func New[V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any, T any](tag Tag, data T) V {
|
func New[V ~struct{ variant[Tag, Shape, Align] }, Tag Discriminant, Shape, Align any, T any](tag Tag, data T) V {
|
||||||
validateVariant[Tag, Shape, Align, T]()
|
validateVariant[Tag, Shape, Align, T]()
|
||||||
var v variant[Tag, Shape, Align]
|
var v variant[Tag, Shape, Align]
|
||||||
v.tag = tag
|
v.tag = tag
|
||||||
@@ -46,7 +35,7 @@ func New[V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Case returns a non-nil *T if the [Variant] case is equal to tag, otherwise it returns nil.
|
// Case returns a non-nil *T if the [Variant] case is equal to tag, otherwise it returns nil.
|
||||||
func Case[T any, V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align any](v *V, tag Tag) *T {
|
func Case[T any, V ~struct{ variant[Tag, Shape, Align] }, Tag Discriminant, Shape, Align any](v *V, tag Tag) *T {
|
||||||
validateVariant[Tag, Shape, Align, T]()
|
validateVariant[Tag, Shape, Align, T]()
|
||||||
v2 := (*variant[Tag, Shape, Align])(unsafe.Pointer(v))
|
v2 := (*variant[Tag, Shape, Align])(unsafe.Pointer(v))
|
||||||
if v2.tag == tag {
|
if v2.tag == tag {
|
||||||
@@ -58,7 +47,6 @@ func Case[T any, V AnyVariant[Tag, Shape, Align], Tag Discriminant, Shape, Align
|
|||||||
// variant is the internal representation of a Component Model variant.
|
// variant is the internal representation of a Component Model variant.
|
||||||
// Shape and Align must be non-zero sized types.
|
// Shape and Align must be non-zero sized types.
|
||||||
type variant[Tag Discriminant, Shape, Align any] struct {
|
type variant[Tag Discriminant, Shape, Align any] struct {
|
||||||
_ HostLayout
|
|
||||||
tag Tag
|
tag Tag
|
||||||
_ [0]Align
|
_ [0]Align
|
||||||
data Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte
|
data Shape // [unsafe.Sizeof(*(*Shape)(unsafe.Pointer(nil)))]byte
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
package gclayout
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// Internal constants for gc layout
|
|
||||||
// See runtime/gc_precise.go
|
|
||||||
|
|
||||||
var (
|
|
||||||
NoPtrs unsafe.Pointer
|
|
||||||
Pointer unsafe.Pointer
|
|
||||||
String unsafe.Pointer
|
|
||||||
Slice unsafe.Pointer
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var sizeBits uintptr
|
|
||||||
|
|
||||||
switch unsafe.Sizeof(uintptr(0)) {
|
|
||||||
case 8:
|
|
||||||
sizeBits = 6
|
|
||||||
case 4:
|
|
||||||
sizeBits = 5
|
|
||||||
case 2:
|
|
||||||
sizeBits = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
var sizeShift = sizeBits + 1
|
|
||||||
|
|
||||||
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
|
||||||
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
|
||||||
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
|
|
||||||
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
|
|
||||||
}
|
|
||||||
@@ -30,6 +30,3 @@ type Task struct {
|
|||||||
// the given function and falls back to the default stack size. It is replaced
|
// the given function and falls back to the default stack size. It is replaced
|
||||||
// with a load from a special section just before codegen.
|
// with a load from a special section just before codegen.
|
||||||
func getGoroutineStackSize(fn uintptr) uintptr
|
func getGoroutineStackSize(fn uintptr) uintptr
|
||||||
|
|
||||||
//go:linkname runtime_alloc runtime.alloc
|
|
||||||
func runtime_alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
|
||||||
|
|||||||
@@ -35,16 +35,11 @@ type state struct {
|
|||||||
type stackState struct {
|
type stackState struct {
|
||||||
// asyncify is the stack pointer of the asyncify stack.
|
// asyncify is the stack pointer of the asyncify stack.
|
||||||
// This starts from the bottom and grows upwards.
|
// This starts from the bottom and grows upwards.
|
||||||
asyncifysp unsafe.Pointer
|
asyncifysp uintptr
|
||||||
|
|
||||||
// asyncify is stack pointer of the C stack.
|
// asyncify is stack pointer of the C stack.
|
||||||
// This starts from the top and grows downwards.
|
// This starts from the top and grows downwards.
|
||||||
csp unsafe.Pointer
|
csp uintptr
|
||||||
|
|
||||||
// Pointer to the first (lowest address) of the stack. It must never be
|
|
||||||
// overwritten. It can be checked from time to time to see whether a stack
|
|
||||||
// overflow happened in the past.
|
|
||||||
canaryPtr *uintptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// start creates and starts a new goroutine with the given function and arguments.
|
// start creates and starts a new goroutine with the given function and arguments.
|
||||||
@@ -68,18 +63,12 @@ func (s *state) initialize(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
|
|||||||
s.args = args
|
s.args = args
|
||||||
|
|
||||||
// Create a stack.
|
// Create a stack.
|
||||||
stack := runtime_alloc(stackSize, nil)
|
stack := make([]uintptr, stackSize/unsafe.Sizeof(uintptr(0)))
|
||||||
|
|
||||||
// Set up the stack canary, a random number that should be checked when
|
|
||||||
// switching from the task back to the scheduler. The stack canary pointer
|
|
||||||
// points to the first word of the stack. If it has changed between now and
|
|
||||||
// the next stack switch, there was a stack overflow.
|
|
||||||
s.canaryPtr = (*uintptr)(stack)
|
|
||||||
*s.canaryPtr = stackCanary
|
|
||||||
|
|
||||||
// Calculate stack base addresses.
|
// Calculate stack base addresses.
|
||||||
s.asyncifysp = unsafe.Add(stack, unsafe.Sizeof(uintptr(0)))
|
s.asyncifysp = uintptr(unsafe.Pointer(&stack[0]))
|
||||||
s.csp = unsafe.Add(stack, stackSize)
|
s.csp = uintptr(unsafe.Pointer(&stack[0])) + uintptr(len(stack))*unsafe.Sizeof(uintptr(0))
|
||||||
|
stack[0] = stackCanary
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname runqueuePushBack runtime.runqueuePushBack
|
//go:linkname runqueuePushBack runtime.runqueuePushBack
|
||||||
@@ -96,11 +85,14 @@ func Current() *Task {
|
|||||||
// Pause suspends the current task and returns to the scheduler.
|
// Pause suspends the current task and returns to the scheduler.
|
||||||
// This function may only be called when running on a goroutine stack, not when running on the system stack.
|
// This function may only be called when running on a goroutine stack, not when running on the system stack.
|
||||||
func Pause() {
|
func Pause() {
|
||||||
if *currentTask.state.canaryPtr != stackCanary {
|
// This is mildly unsafe but this is also the only place we can do this.
|
||||||
|
if *(*uintptr)(unsafe.Pointer(currentTask.state.asyncifysp)) != stackCanary {
|
||||||
runtimePanic("stack overflow")
|
runtimePanic("stack overflow")
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTask.state.unwind()
|
currentTask.state.unwind()
|
||||||
|
|
||||||
|
*(*uintptr)(unsafe.Pointer(currentTask.state.asyncifysp)) = stackCanary
|
||||||
}
|
}
|
||||||
|
|
||||||
//export tinygo_unwind
|
//export tinygo_unwind
|
||||||
@@ -121,7 +113,7 @@ func (t *Task) Resume() {
|
|||||||
}
|
}
|
||||||
currentTask = prevTask
|
currentTask = prevTask
|
||||||
t.gcData.swap()
|
t.gcData.swap()
|
||||||
if uintptr(t.state.asyncifysp) > uintptr(t.state.csp) {
|
if t.state.asyncifysp > t.state.csp {
|
||||||
runtimePanic("stack overflow")
|
runtimePanic("stack overflow")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ var startTask [0]uint8
|
|||||||
//go:linkname runqueuePushBack runtime.runqueuePushBack
|
//go:linkname runqueuePushBack runtime.runqueuePushBack
|
||||||
func runqueuePushBack(*Task)
|
func runqueuePushBack(*Task)
|
||||||
|
|
||||||
|
//go:linkname runtime_alloc runtime.alloc
|
||||||
|
func runtime_alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
||||||
|
|
||||||
// start creates and starts a new goroutine with the given function and arguments.
|
// start creates and starts a new goroutine with the given function and arguments.
|
||||||
// The new goroutine is scheduled to run later.
|
// The new goroutine is scheduled to run later.
|
||||||
func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
|
func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package environment
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/environment@0.2.0 get-environment
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetEnvironment(result *cm.List[[2]string])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/environment@0.2.0 get-arguments
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetArguments(result *cm.List[string])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_InitialCWD(result *cm.Option[string])
|
|
||||||
@@ -26,6 +26,10 @@ func GetEnvironment() (result cm.List[[2]string]) {
|
|||||||
return
|
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".
|
// GetArguments represents the imported function "get-arguments".
|
||||||
//
|
//
|
||||||
// Get the POSIX-style arguments to the program.
|
// Get the POSIX-style arguments to the program.
|
||||||
@@ -38,6 +42,10 @@ func GetArguments() (result cm.List[string]) {
|
|||||||
return
|
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".
|
// InitialCWD represents the imported function "initial-cwd".
|
||||||
//
|
//
|
||||||
// Return a path that programs should use as their initial current working
|
// Return a path that programs should use as their initial current working
|
||||||
@@ -50,3 +58,7 @@ func InitialCWD() (result cm.Option[string]) {
|
|||||||
wasmimport_InitialCWD(&result)
|
wasmimport_InitialCWD(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/environment@0.2.0 initial-cwd
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_InitialCWD(result *cm.Option[string])
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package exit
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/exit@0.2.0 exit
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_Exit(status0 uint32)
|
|
||||||
@@ -19,3 +19,7 @@ func Exit(status cm.BoolResult) {
|
|||||||
wasmimport_Exit((uint32)(status0))
|
wasmimport_Exit((uint32)(status0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/exit@0.2.0 exit
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_Exit(status0 uint32)
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package run
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmexport wasi:cli/run@0.2.0#run
|
|
||||||
//export wasi:cli/run@0.2.0#run
|
|
||||||
func wasmexport_Run() (result0 uint32) {
|
|
||||||
result := Exports.Run()
|
|
||||||
result0 = cm.BoolToU32(result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -2,3 +2,15 @@
|
|||||||
|
|
||||||
// Package run represents the exported interface "wasi:cli/run@0.2.0".
|
// Package run represents the exported interface "wasi:cli/run@0.2.0".
|
||||||
package run
|
package run
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/cm"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:wasmexport wasi:cli/run@0.2.0#run
|
||||||
|
//export wasi:cli/run@0.2.0#run
|
||||||
|
func wasmexport_Run() (result0 uint32) {
|
||||||
|
result := Exports.Run()
|
||||||
|
result0 = cm.BoolToU32(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package stderr
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetStderr() (result0 uint32)
|
|
||||||
@@ -8,18 +8,17 @@ import (
|
|||||||
"internal/wasi/io/v0.2.0/streams"
|
"internal/wasi/io/v0.2.0/streams"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OutputStream represents the imported type alias "wasi:cli/stderr@0.2.0#output-stream".
|
|
||||||
//
|
|
||||||
// See [streams.OutputStream] for more information.
|
|
||||||
type OutputStream = streams.OutputStream
|
|
||||||
|
|
||||||
// GetStderr represents the imported function "get-stderr".
|
// GetStderr represents the imported function "get-stderr".
|
||||||
//
|
//
|
||||||
// get-stderr: func() -> output-stream
|
// get-stderr: func() -> output-stream
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetStderr() (result OutputStream) {
|
func GetStderr() (result streams.OutputStream) {
|
||||||
result0 := wasmimport_GetStderr()
|
result0 := wasmimport_GetStderr()
|
||||||
result = cm.Reinterpret[OutputStream]((uint32)(result0))
|
result = cm.Reinterpret[streams.OutputStream]((uint32)(result0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/stderr@0.2.0 get-stderr
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetStderr() (result0 uint32)
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package stdin
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetStdin() (result0 uint32)
|
|
||||||
@@ -8,18 +8,17 @@ import (
|
|||||||
"internal/wasi/io/v0.2.0/streams"
|
"internal/wasi/io/v0.2.0/streams"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InputStream represents the imported type alias "wasi:cli/stdin@0.2.0#input-stream".
|
|
||||||
//
|
|
||||||
// See [streams.InputStream] for more information.
|
|
||||||
type InputStream = streams.InputStream
|
|
||||||
|
|
||||||
// GetStdin represents the imported function "get-stdin".
|
// GetStdin represents the imported function "get-stdin".
|
||||||
//
|
//
|
||||||
// get-stdin: func() -> input-stream
|
// get-stdin: func() -> input-stream
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetStdin() (result InputStream) {
|
func GetStdin() (result streams.InputStream) {
|
||||||
result0 := wasmimport_GetStdin()
|
result0 := wasmimport_GetStdin()
|
||||||
result = cm.Reinterpret[InputStream]((uint32)(result0))
|
result = cm.Reinterpret[streams.InputStream]((uint32)(result0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/stdin@0.2.0 get-stdin
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetStdin() (result0 uint32)
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package stdout
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetStdout() (result0 uint32)
|
|
||||||
@@ -8,18 +8,17 @@ import (
|
|||||||
"internal/wasi/io/v0.2.0/streams"
|
"internal/wasi/io/v0.2.0/streams"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OutputStream represents the imported type alias "wasi:cli/stdout@0.2.0#output-stream".
|
|
||||||
//
|
|
||||||
// See [streams.OutputStream] for more information.
|
|
||||||
type OutputStream = streams.OutputStream
|
|
||||||
|
|
||||||
// GetStdout represents the imported function "get-stdout".
|
// GetStdout represents the imported function "get-stdout".
|
||||||
//
|
//
|
||||||
// get-stdout: func() -> output-stream
|
// get-stdout: func() -> output-stream
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetStdout() (result OutputStream) {
|
func GetStdout() (result streams.OutputStream) {
|
||||||
result0 := wasmimport_GetStdout()
|
result0 := wasmimport_GetStdout()
|
||||||
result = cm.Reinterpret[OutputStream]((uint32)(result0))
|
result = cm.Reinterpret[streams.OutputStream]((uint32)(result0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/stdout@0.2.0 get-stdout
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetStdout() (result0 uint32)
|
||||||
|
|||||||
@@ -30,3 +30,7 @@ func (self TerminalInput) ResourceDrop() {
|
|||||||
wasmimport_TerminalInputResourceDrop((uint32)(self0))
|
wasmimport_TerminalInputResourceDrop((uint32)(self0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_TerminalInputResourceDrop(self0 uint32)
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package terminalinput
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/terminal-input@0.2.0 [resource-drop]terminal-input
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_TerminalInputResourceDrop(self0 uint32)
|
|
||||||
@@ -30,3 +30,7 @@ func (self TerminalOutput) ResourceDrop() {
|
|||||||
wasmimport_TerminalOutputResourceDrop((uint32)(self0))
|
wasmimport_TerminalOutputResourceDrop((uint32)(self0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_TerminalOutputResourceDrop(self0 uint32)
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package terminaloutput
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/terminal-output@0.2.0 [resource-drop]terminal-output
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_TerminalOutputResourceDrop(self0 uint32)
|
|
||||||
@@ -11,11 +11,6 @@ import (
|
|||||||
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
|
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TerminalOutput represents the imported type alias "wasi:cli/terminal-stderr@0.2.0#terminal-output".
|
|
||||||
//
|
|
||||||
// See [terminaloutput.TerminalOutput] for more information.
|
|
||||||
type TerminalOutput = terminaloutput.TerminalOutput
|
|
||||||
|
|
||||||
// GetTerminalStderr represents the imported function "get-terminal-stderr".
|
// GetTerminalStderr represents the imported function "get-terminal-stderr".
|
||||||
//
|
//
|
||||||
// If stderr is connected to a terminal, return a `terminal-output` handle
|
// If stderr is connected to a terminal, return a `terminal-output` handle
|
||||||
@@ -24,7 +19,11 @@ type TerminalOutput = terminaloutput.TerminalOutput
|
|||||||
// get-terminal-stderr: func() -> option<terminal-output>
|
// get-terminal-stderr: func() -> option<terminal-output>
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetTerminalStderr() (result cm.Option[TerminalOutput]) {
|
func GetTerminalStderr() (result cm.Option[terminaloutput.TerminalOutput]) {
|
||||||
wasmimport_GetTerminalStderr(&result)
|
wasmimport_GetTerminalStderr(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetTerminalStderr(result *cm.Option[terminaloutput.TerminalOutput])
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package terminalstderr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/terminal-stderr@0.2.0 get-terminal-stderr
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetTerminalStderr(result *cm.Option[TerminalOutput])
|
|
||||||
@@ -11,11 +11,6 @@ import (
|
|||||||
terminalinput "internal/wasi/cli/v0.2.0/terminal-input"
|
terminalinput "internal/wasi/cli/v0.2.0/terminal-input"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TerminalInput represents the imported type alias "wasi:cli/terminal-stdin@0.2.0#terminal-input".
|
|
||||||
//
|
|
||||||
// See [terminalinput.TerminalInput] for more information.
|
|
||||||
type TerminalInput = terminalinput.TerminalInput
|
|
||||||
|
|
||||||
// GetTerminalStdin represents the imported function "get-terminal-stdin".
|
// GetTerminalStdin represents the imported function "get-terminal-stdin".
|
||||||
//
|
//
|
||||||
// If stdin is connected to a terminal, return a `terminal-input` handle
|
// If stdin is connected to a terminal, return a `terminal-input` handle
|
||||||
@@ -24,7 +19,11 @@ type TerminalInput = terminalinput.TerminalInput
|
|||||||
// get-terminal-stdin: func() -> option<terminal-input>
|
// get-terminal-stdin: func() -> option<terminal-input>
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetTerminalStdin() (result cm.Option[TerminalInput]) {
|
func GetTerminalStdin() (result cm.Option[terminalinput.TerminalInput]) {
|
||||||
wasmimport_GetTerminalStdin(&result)
|
wasmimport_GetTerminalStdin(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetTerminalStdin(result *cm.Option[terminalinput.TerminalInput])
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package terminalstdin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/terminal-stdin@0.2.0 get-terminal-stdin
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetTerminalStdin(result *cm.Option[TerminalInput])
|
|
||||||
@@ -11,11 +11,6 @@ import (
|
|||||||
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
|
terminaloutput "internal/wasi/cli/v0.2.0/terminal-output"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TerminalOutput represents the imported type alias "wasi:cli/terminal-stdout@0.2.0#terminal-output".
|
|
||||||
//
|
|
||||||
// See [terminaloutput.TerminalOutput] for more information.
|
|
||||||
type TerminalOutput = terminaloutput.TerminalOutput
|
|
||||||
|
|
||||||
// GetTerminalStdout represents the imported function "get-terminal-stdout".
|
// GetTerminalStdout represents the imported function "get-terminal-stdout".
|
||||||
//
|
//
|
||||||
// If stdout is connected to a terminal, return a `terminal-output` handle
|
// If stdout is connected to a terminal, return a `terminal-output` handle
|
||||||
@@ -24,7 +19,11 @@ type TerminalOutput = terminaloutput.TerminalOutput
|
|||||||
// get-terminal-stdout: func() -> option<terminal-output>
|
// get-terminal-stdout: func() -> option<terminal-output>
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetTerminalStdout() (result cm.Option[TerminalOutput]) {
|
func GetTerminalStdout() (result cm.Option[terminaloutput.TerminalOutput]) {
|
||||||
wasmimport_GetTerminalStdout(&result)
|
wasmimport_GetTerminalStdout(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetTerminalStdout(result *cm.Option[terminaloutput.TerminalOutput])
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package terminalstdout
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:cli@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:cli/terminal-stdout@0.2.0 get-terminal-stdout
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetTerminalStdout(result *cm.Option[TerminalOutput])
|
|
||||||
@@ -19,11 +19,6 @@ import (
|
|||||||
"internal/wasi/io/v0.2.0/poll"
|
"internal/wasi/io/v0.2.0/poll"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pollable represents the imported type alias "wasi:clocks/monotonic-clock@0.2.0#pollable".
|
|
||||||
//
|
|
||||||
// See [poll.Pollable] for more information.
|
|
||||||
type Pollable = poll.Pollable
|
|
||||||
|
|
||||||
// Instant represents the u64 "wasi:clocks/monotonic-clock@0.2.0#instant".
|
// Instant represents the u64 "wasi:clocks/monotonic-clock@0.2.0#instant".
|
||||||
//
|
//
|
||||||
// An instant in time, in nanoseconds. An instant is relative to an
|
// An instant in time, in nanoseconds. An instant is relative to an
|
||||||
@@ -56,6 +51,10 @@ func Now() (result Instant) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_Now() (result0 uint64)
|
||||||
|
|
||||||
// Resolution represents the imported function "resolution".
|
// Resolution represents the imported function "resolution".
|
||||||
//
|
//
|
||||||
// Query the resolution of the clock. Returns the duration of time
|
// Query the resolution of the clock. Returns the duration of time
|
||||||
@@ -70,6 +69,10 @@ func Resolution() (result Duration) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_Resolution() (result0 uint64)
|
||||||
|
|
||||||
// SubscribeInstant represents the imported function "subscribe-instant".
|
// SubscribeInstant represents the imported function "subscribe-instant".
|
||||||
//
|
//
|
||||||
// Create a `pollable` which will resolve once the specified instant
|
// Create a `pollable` which will resolve once the specified instant
|
||||||
@@ -78,13 +81,17 @@ func Resolution() (result Duration) {
|
|||||||
// subscribe-instant: func(when: instant) -> pollable
|
// subscribe-instant: func(when: instant) -> pollable
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func SubscribeInstant(when Instant) (result Pollable) {
|
func SubscribeInstant(when Instant) (result poll.Pollable) {
|
||||||
when0 := (uint64)(when)
|
when0 := (uint64)(when)
|
||||||
result0 := wasmimport_SubscribeInstant((uint64)(when0))
|
result0 := wasmimport_SubscribeInstant((uint64)(when0))
|
||||||
result = cm.Reinterpret[Pollable]((uint32)(result0))
|
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32)
|
||||||
|
|
||||||
// SubscribeDuration represents the imported function "subscribe-duration".
|
// SubscribeDuration represents the imported function "subscribe-duration".
|
||||||
//
|
//
|
||||||
// Create a `pollable` which will resolve once the given duration has
|
// Create a `pollable` which will resolve once the given duration has
|
||||||
@@ -94,9 +101,13 @@ func SubscribeInstant(when Instant) (result Pollable) {
|
|||||||
// subscribe-duration: func(when: duration) -> pollable
|
// subscribe-duration: func(when: duration) -> pollable
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func SubscribeDuration(when Duration) (result Pollable) {
|
func SubscribeDuration(when Duration) (result poll.Pollable) {
|
||||||
when0 := (uint64)(when)
|
when0 := (uint64)(when)
|
||||||
result0 := wasmimport_SubscribeDuration((uint64)(when0))
|
result0 := wasmimport_SubscribeDuration((uint64)(when0))
|
||||||
result = cm.Reinterpret[Pollable]((uint32)(result0))
|
result = cm.Reinterpret[poll.Pollable]((uint32)(result0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_SubscribeDuration(when0 uint64) (result0 uint32)
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package monotonicclock
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 now
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_Now() (result0 uint64)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 resolution
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_Resolution() (result0 uint64)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-instant
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_SubscribeInstant(when0 uint64) (result0 uint32)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:clocks/monotonic-clock@0.2.0 subscribe-duration
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_SubscribeDuration(when0 uint64) (result0 uint32)
|
|
||||||
@@ -18,10 +18,6 @@
|
|||||||
// It is intended for reporting the current date and time for humans.
|
// It is intended for reporting the current date and time for humans.
|
||||||
package wallclock
|
package wallclock
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DateTime represents the record "wasi:clocks/wall-clock@0.2.0#datetime".
|
// DateTime represents the record "wasi:clocks/wall-clock@0.2.0#datetime".
|
||||||
//
|
//
|
||||||
// A time and date in seconds plus nanoseconds.
|
// A time and date in seconds plus nanoseconds.
|
||||||
@@ -31,7 +27,6 @@ import (
|
|||||||
// nanoseconds: u32,
|
// nanoseconds: u32,
|
||||||
// }
|
// }
|
||||||
type DateTime struct {
|
type DateTime struct {
|
||||||
_ cm.HostLayout
|
|
||||||
Seconds uint64
|
Seconds uint64
|
||||||
Nanoseconds uint32
|
Nanoseconds uint32
|
||||||
}
|
}
|
||||||
@@ -60,6 +55,10 @@ func Now() (result DateTime) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:clocks/wall-clock@0.2.0 now
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_Now(result *DateTime)
|
||||||
|
|
||||||
// Resolution represents the imported function "resolution".
|
// Resolution represents the imported function "resolution".
|
||||||
//
|
//
|
||||||
// Query the resolution of the clock.
|
// Query the resolution of the clock.
|
||||||
@@ -73,3 +72,7 @@ func Resolution() (result DateTime) {
|
|||||||
wasmimport_Resolution(&result)
|
wasmimport_Resolution(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_Resolution(result *DateTime)
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package wallclock
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:clocks@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:clocks/wall-clock@0.2.0 now
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_Now(result *DateTime)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:clocks/wall-clock@0.2.0 resolution
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_Resolution(result *DateTime)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package preopens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_GetDirectories(result *cm.List[cm.Tuple[Descriptor, string]])
|
|
||||||
@@ -8,11 +8,6 @@ import (
|
|||||||
"internal/wasi/filesystem/v0.2.0/types"
|
"internal/wasi/filesystem/v0.2.0/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Descriptor represents the imported type alias "wasi:filesystem/preopens@0.2.0#descriptor".
|
|
||||||
//
|
|
||||||
// See [types.Descriptor] for more information.
|
|
||||||
type Descriptor = types.Descriptor
|
|
||||||
|
|
||||||
// GetDirectories represents the imported function "get-directories".
|
// GetDirectories represents the imported function "get-directories".
|
||||||
//
|
//
|
||||||
// Return the set of preopened directories, and their path.
|
// Return the set of preopened directories, and their path.
|
||||||
@@ -20,7 +15,11 @@ type Descriptor = types.Descriptor
|
|||||||
// get-directories: func() -> list<tuple<descriptor, string>>
|
// get-directories: func() -> list<tuple<descriptor, string>>
|
||||||
//
|
//
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func GetDirectories() (result cm.List[cm.Tuple[Descriptor, string]]) {
|
func GetDirectories() (result cm.List[cm.Tuple[types.Descriptor, string]]) {
|
||||||
wasmimport_GetDirectories(&result)
|
wasmimport_GetDirectories(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:wasmimport wasi:filesystem/preopens@0.2.0 get-directories
|
||||||
|
//go:noescape
|
||||||
|
func wasmimport_GetDirectories(result *cm.List[cm.Tuple[types.Descriptor, string]])
|
||||||
|
|||||||
@@ -8,15 +8,18 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DateTimeShape is used for storage in variant or result types.
|
||||||
|
type DateTimeShape struct {
|
||||||
|
shape [unsafe.Sizeof(wallclock.DateTime{})]byte
|
||||||
|
}
|
||||||
|
|
||||||
// MetadataHashValueShape is used for storage in variant or result types.
|
// MetadataHashValueShape is used for storage in variant or result types.
|
||||||
type MetadataHashValueShape struct {
|
type MetadataHashValueShape struct {
|
||||||
_ cm.HostLayout
|
|
||||||
shape [unsafe.Sizeof(MetadataHashValue{})]byte
|
shape [unsafe.Sizeof(MetadataHashValue{})]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// TupleListU8BoolShape is used for storage in variant or result types.
|
// TupleListU8BoolShape is used for storage in variant or result types.
|
||||||
type TupleListU8BoolShape struct {
|
type TupleListU8BoolShape struct {
|
||||||
_ cm.HostLayout
|
|
||||||
shape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte
|
shape [unsafe.Sizeof(cm.Tuple[cm.List[uint8], bool]{})]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,12 +42,10 @@ func lower_NewTimestamp(v NewTimestamp) (f0 uint32, f1 uint64, f2 uint32) {
|
|||||||
|
|
||||||
// DescriptorStatShape is used for storage in variant or result types.
|
// DescriptorStatShape is used for storage in variant or result types.
|
||||||
type DescriptorStatShape struct {
|
type DescriptorStatShape struct {
|
||||||
_ cm.HostLayout
|
|
||||||
shape [unsafe.Sizeof(DescriptorStat{})]byte
|
shape [unsafe.Sizeof(DescriptorStat{})]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// OptionDirectoryEntryShape is used for storage in variant or result types.
|
// OptionDirectoryEntryShape is used for storage in variant or result types.
|
||||||
type OptionDirectoryEntryShape struct {
|
type OptionDirectoryEntryShape struct {
|
||||||
_ cm.HostLayout
|
|
||||||
shape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte
|
shape [unsafe.Sizeof(cm.Option[DirectoryEntry]{})]byte
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,133 +0,0 @@
|
|||||||
// Code generated by wit-bindgen-go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"internal/cm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file contains wasmimport and wasmexport declarations for "wasi:filesystem@0.2.0".
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]descriptor
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorResourceDrop(self0 uint32)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.advise
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorAdvise(self0 uint32, offset0 uint64, length0 uint64, advice0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.append-via-stream
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorAppendViaStream(self0 uint32, result *cm.Result[OutputStream, OutputStream, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.create-directory-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorCreateDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-flags
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorGetFlags(self0 uint32, result *cm.Result[DescriptorFlags, DescriptorFlags, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.get-type
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorGetType(self0 uint32, result *cm.Result[DescriptorType, DescriptorType, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.is-same-object
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorIsSameObject(self0 uint32, other0 uint32) (result0 uint32)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.link-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorLinkAt(self0 uint32, oldPathFlags0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorMetadataHash(self0 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.metadata-hash-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorMetadataHashAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[MetadataHashValueShape, MetadataHashValue, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.open-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorOpenAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, openFlags0 uint32, flags0 uint32, result *cm.Result[Descriptor, Descriptor, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorRead(self0 uint32, length0 uint64, offset0 uint64, result *cm.Result[TupleListU8BoolShape, cm.Tuple[cm.List[uint8], bool], ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-directory
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorReadDirectory(self0 uint32, result *cm.Result[DirectoryEntryStream, DirectoryEntryStream, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.read-via-stream
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorReadViaStream(self0 uint32, offset0 uint64, result *cm.Result[InputStream, InputStream, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.readlink-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorReadLinkAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[string, string, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.remove-directory-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorRemoveDirectoryAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.rename-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorRenameAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newDescriptor0 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-size
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorSetSize(self0 uint32, size0 uint64, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorSetTimes(self0 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.set-times-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorSetTimesAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, dataAccessTimestamp0 uint32, dataAccessTimestamp1 uint64, dataAccessTimestamp2 uint32, dataModificationTimestamp0 uint32, dataModificationTimestamp1 uint64, dataModificationTimestamp2 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorStat(self0 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.stat-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorStatAt(self0 uint32, pathFlags0 uint32, path0 *uint8, path1 uint32, result *cm.Result[DescriptorStatShape, DescriptorStat, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.symlink-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorSymlinkAt(self0 uint32, oldPath0 *uint8, oldPath1 uint32, newPath0 *uint8, newPath1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorSync(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.sync-data
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorSyncData(self0 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.unlink-file-at
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorUnlinkFileAt(self0 uint32, path0 *uint8, path1 uint32, result *cm.Result[ErrorCode, struct{}, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorWrite(self0 uint32, buffer0 *uint8, buffer1 uint32, offset0 uint64, result *cm.Result[uint64, FileSize, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]descriptor.write-via-stream
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DescriptorWriteViaStream(self0 uint32, offset0 uint64, result *cm.Result[OutputStream, OutputStream, ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [resource-drop]directory-entry-stream
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DirectoryEntryStreamResourceDrop(self0 uint32)
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 [method]directory-entry-stream.read-directory-entry
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_DirectoryEntryStreamReadDirectoryEntry(self0 uint32, result *cm.Result[OptionDirectoryEntryShape, cm.Option[DirectoryEntry], ErrorCode])
|
|
||||||
|
|
||||||
//go:wasmimport wasi:filesystem/types@0.2.0 filesystem-error-code
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_FilesystemErrorCode(err0 uint32, result *cm.Option[ErrorCode])
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user